Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(layer-tabs): add collapsible layer-selector, highlight selected … #123

Merged
merged 4 commits into from
Oct 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/scripts/actions/set-selected-layer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const SET_SELECTED_LAYER_ID = 'SET_SELECTED_LAYER_ID';

export type LayerId = string;
export type LayerId = string | null;

export interface SetSelectedLayerIdAction {
type: typeof SET_SELECTED_LAYER_ID;
Expand Down
1 change: 1 addition & 0 deletions src/scripts/components/app/app.styl
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

.app
height: 100%
font-family: Arial, Helvetica, sans-serif
16 changes: 13 additions & 3 deletions src/scripts/components/layer-list/layer-list.styl
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,26 @@
padding: 0
margin: 0
background-color: #fff
list-style: none

.layerItem
padding: 15px
font-size: 1.1em

.layerItem:hover,
.layerItem:focus
background-color: #e0f1ff

.layerItemSelected,
.layerItemSelected:hover
.layerItemSelected:focus
background-color:#a8d7ff

.subLayerItem
margin: 5px
padding: 15px
font-size: 1em

.layerItem:hover,
.layerItem:focus
background-color: #e0f1ff
.subLayerItemSelected
background-color: #a8d7ff

20 changes: 16 additions & 4 deletions src/scripts/components/layer-list/layer-list.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
import React, {FunctionComponent, MouseEvent} from 'react';
import cx from 'classnames';
import {Layer} from '../../actions/fetch-layers';
import styles from './layer-list.styl';

interface Props {
layers: Layer[];
selected: string;
selected: string | null;
onSelect: (id: string) => void;
}

const LayerList: FunctionComponent<Props> = ({layers, onSelect}) => (
const LayerList: FunctionComponent<Props> = ({layers, selected, onSelect}) => (
<ul className={styles.layerList}>
{layers.map(layer => {
const layerClickHandler = () => {
if (layer.subLayers.length === 0) {
onSelect(layer.id);
}
};
const isSelected = selected === layer.id;
const layerItemClasses = cx(
styles.layerItem,
isSelected && styles.layerItemSelected
);

return (
<li
className={styles.layerItem}
className={layerItemClasses}
key={layer.id}
onClick={() => layerClickHandler()}>
{layer.name}
Expand All @@ -31,9 +37,15 @@ const LayerList: FunctionComponent<Props> = ({layers, onSelect}) => (
event.stopPropagation();
onSelect(subLayer.id);
};
const isSubSelected = selected === subLayer.id;
const subLayerItemClasses = cx(
styles.subLayerItem,
isSubSelected && styles.subLayerItemSelected
);

return (
<li
className={styles.subLayerItem}
className={subLayerItemClasses}
key={subLayer.id}
onClick={event => subLayerClickHandler(event)}>
{subLayer.name}
Expand Down
38 changes: 30 additions & 8 deletions src/scripts/components/layer-selector/layer-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {FunctionComponent, useEffect, useState} from 'react';
import {useSelector, useDispatch} from 'react-redux';
import {layersSelector} from '../../reducers/layers';
import {selectedLayerIdSelector} from '../../reducers/selected-layer-id';
import fetchLayers from '../../actions/fetch-layers';
import {setSelectedLayerIdAction} from '../../actions/set-selected-layer';
import LayerList from '../layer-list/layer-list';
Expand All @@ -9,6 +10,7 @@ import styles from './layer-selector.styl';

const LayerSelector: FunctionComponent<{}> = () => {
const layers = useSelector(layersSelector);
const layerIds = useSelector(selectedLayerIdSelector);
const dispatch = useDispatch();
const tabs = [
{
Expand All @@ -22,7 +24,27 @@ const LayerSelector: FunctionComponent<{}> = () => {
];

const [activeTabId, setActiveTabId] = useState(tabs[0].id);
const [isOpen, setIsOpen] = useState(false);
const isMainTabSelected = activeTabId === tabs[0].id;
const selectedLayer = isMainTabSelected ? layerIds.main : layerIds.compare;

const onTabClick = (id: string) => {
setActiveTabId(id);

if (!isOpen) {
setIsOpen(true);
return;
}

if (activeTabId === id) {
setIsOpen(false);
}
};

const onLayerClick = (id: string) => {
const newId = selectedLayer === id ? null : id;
dispatch(setSelectedLayerIdAction(newId, isMainTabSelected));
};

useEffect(() => {
dispatch(fetchLayers());
Expand All @@ -33,15 +55,15 @@ const LayerSelector: FunctionComponent<{}> = () => {
<Tabs
tabs={tabs}
activeTabId={activeTabId}
onTabChanged={id => setActiveTabId(id)}
/>
<LayerList
layers={layers}
selected={'layer1'}
onSelect={id =>
dispatch(setSelectedLayerIdAction(id, isMainTabSelected))
}
onTabChanged={id => onTabClick(id)}
/>
{isOpen && (
<LayerList
layers={layers}
selected={selectedLayer}
onSelect={id => onLayerClick(id)}
/>
)}
</div>
);
};
Expand Down
9 changes: 6 additions & 3 deletions src/scripts/components/tab/tab.styl
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
.btn
.tab
width: 50%
padding: 20px
border-radius: 10px 10px 0 0
font-size: 1.3em
outline: 0

.btnInactive
background-color: #141414
color: #fff
border: 1px solid #ccc

.tabActive
background-color: #fff
color: #141414
border: 1px solid #ccc
10 changes: 5 additions & 5 deletions src/scripts/components/tab/tab.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {FunctionComponent} from 'react';
import cx from 'classnames';
import styles from './tab.styl';
import classNames from 'classnames';

interface Props {
id: string;
Expand All @@ -14,11 +14,11 @@ const Tab: FunctionComponent<Props> = ({
onSelectTabId,
children
}) => {
const btnClass = classNames(styles.btn, {
[styles.btnInactive]: activeTabId !== id
});
const isActive = activeTabId === id;
const tabClasses = cx(styles.tab, isActive && styles.tabActive);

return (
<button className={btnClass} onClick={() => onSelectTabId(id)}>
<button className={tabClasses} onClick={() => onSelectTabId(id)}>
{children}
</button>
);
Expand Down
5 changes: 4 additions & 1 deletion src/scripts/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export type Action = FetchLayersSuccessAction | SetSelectedLayerIdAction;

const initialState: State = {
layers: [],
selectedLayer: []
selectedLayer: {
main: null,
compare: null
}
};

function reducer(state: State = initialState, action: Action): State {
Expand Down
19 changes: 14 additions & 5 deletions src/scripts/reducers/selected-layer-id.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import {SET_SELECTED_LAYER_ID, LayerId} from '../actions/set-selected-layer';
import {Action, State} from './index';

export type SelectedLayersState = LayerId[];
export interface SelectedLayersState {
main: LayerId | null;
compare: LayerId | null;
}

const initialState = {
main: null,
compare: null
};

function selectedLayerReducer(
state: SelectedLayersState = [],
state: SelectedLayersState = initialState,
action: Action
): SelectedLayersState {
switch (action.type) {
case SET_SELECTED_LAYER_ID:
const newState = [...state];
newState[action.isPrimary ? 0 : 1] = action.layerId;
const newState = {...state};
const key = action.isPrimary ? 'main' : 'compare';
newState[key] = action.layerId;
return newState;
default:
return state;
}
}
export function selectedLayerIdSelector(state: State) {
export function selectedLayerIdSelector(state: State): SelectedLayersState {
return state.selectedLayer;
}
export default selectedLayerReducer;