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 2 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

16 changes: 11 additions & 5 deletions src/scripts/components/layer-list/layer-list.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
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 layerItemClass = cx(styles.layerItem, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest this as it is a bit easier to read:

const isSelected = selected === layer.id;
const layerItemClasses = cx(styles.layerItem, isSelected && styles.layerItemSelected);

Also note the plural of the variable name layerItemClasses;

[styles.layerItemSelected]: selected === layer.id
});
return (
<li
className={styles.layerItem}
className={layerItemClass}
key={layer.id}
onClick={() => layerClickHandler()}>
{layer.name}
Expand All @@ -31,9 +34,12 @@ const LayerList: FunctionComponent<Props> = ({layers, onSelect}) => (
event.stopPropagation();
onSelect(subLayer.id);
};
const subLayerItemClass = cx(styles.subLayerItem, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

[styles.subLayerItemSelected]: selected === subLayer.id
});
return (
<li
className={styles.subLayerItem}
className={subLayerItemClass}
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
4 changes: 2 additions & 2 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,7 +14,7 @@ const Tab: FunctionComponent<Props> = ({
onSelectTabId,
children
}) => {
const btnClass = classNames(styles.btn, {
const btnClass = cx(styles.btn, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also same as above

[styles.btnInactive]: activeTabId !== id
});
return (
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;