Skip to content

Commit

Permalink
Merge pull request #1704: Redesign panel sections in sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
victorlin authored Nov 14, 2023
2 parents 477d27b + e018f30 commit 4e2de85
Show file tree
Hide file tree
Showing 31 changed files with 424 additions and 250 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

* Redesigned the panel sections in the sidebar. ([#1704](https://github.com/nextstrain/auspice/pull/1704))
* Moved panel visibility toggles to the header.
* Added the ability to show/hide panel options.
* customisation: Renamed `sidebarTheme.unselectedBackground` to a more generic name, `sidebarTheme.alternateBackground`, while keeping backwards compatibility. ([#1704](https://github.com/nextstrain/auspice/pull/1704/commits/1ad4376bb3be9787181110d47fe8c5f26a207896))

## version 2.50.0 - 2023/10/30


Expand Down
34 changes: 18 additions & 16 deletions docs/customise-client/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,27 @@ For instance, here is the customisation used by nextstrain.org:
"font-family": "Lato, Helvetica Neue, Helvetica, sans-serif",
"selectedColor": "#5097BA",
"unselectedColor": "#333",
"unselectedBackground": "#888"
"alternateBackground": "#888"
}
}
+--------------------------+------------------------------+----------------------------------------------------+
| Properties | CSS string of | Description |
+==========================+==============================+====================================================+
| selectedColor | color | Text color of selected text / button text |
+--------------------------+------------------------------+----------------------------------------------------+
| unselectedColor | color | Text color of unselected text / button text |
+--------------------------+------------------------------+----------------------------------------------------+
| color | color | Text color of all other text |
+--------------------------+------------------------------+----------------------------------------------------+
| unselectedBackground | color | Background color of unselected toggle |
+--------------------------+------------------------------+----------------------------------------------------+
| font-family | font | Font used throughout the sidebar |
+--------------------------+------------------------------+----------------------------------------------------+
| background | color | Background color of the entire sidebar |
+--------------------------+------------------------------+----------------------------------------------------+
+-----------------------------------+---------------+------------------------------------------------------------------------------+
| Properties | CSS string of | Description |
+===================================+===============+==============================================================================+
| selectedColor | color | Text color of selected text / button text |
+-----------------------------------+---------------+------------------------------------------------------------------------------+
| unselectedColor | color | Text color of unselected text / button text |
+-----------------------------------+---------------+------------------------------------------------------------------------------+
| color | color | Text color of all other text |
+-----------------------------------+---------------+------------------------------------------------------------------------------+
| unselectedBackground (deprecated) | color | Old key for ``alternateBackground`` |
+-----------------------------------+---------------+------------------------------------------------------------------------------+
| alternateBackground | color | Background color of some elements (unselected toggle, panel section borders) |
+-----------------------------------+---------------+------------------------------------------------------------------------------+
| font-family | font | Font used throughout the sidebar |
+-----------------------------------+---------------+------------------------------------------------------------------------------+
| background | color | Background color of the entire sidebar |
+-----------------------------------+---------------+------------------------------------------------------------------------------+

Components
----------
Expand Down
26 changes: 0 additions & 26 deletions src/components/controls/annotatedHeader.tsx

This file was deleted.

42 changes: 42 additions & 0 deletions src/components/controls/annotatedTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react";
import { useSelector } from "react-redux";
import { FaInfoCircle } from "react-icons/fa";
import {TitleAndIconContainer, StyledTooltip, HeaderIconContainer, HeaderTitle} from "./styles";
import { RootState } from "../../store";

/** Title to display for the control. */
export type Title = string;

/** Informational tooltip element to display on hover. */
export type Tooltip = JSX.Element;

type Props = {
title: Title
tooltip?: Tooltip
}

/**
* A title and tooltip to be shown in a control header.
* The tooltip is not shown on mobile.
*/
export const AnnotatedTitle = ({title, tooltip=undefined}: Props) => {
const mobile = useSelector((state: RootState) => state.general.mobileDisplay);

return (
<TitleAndIconContainer>
<HeaderTitle>{title}</HeaderTitle>
{tooltip && !mobile && (
<>
<HeaderIconContainer data-tip data-for={title}
// Don't allow any parent onClick callbacks to run.
onClick={(event) => event.stopPropagation()}>
<FaInfoCircle/>
</HeaderIconContainer>
<StyledTooltip place="bottom" type="dark" effect="solid" id={title}>
{tooltip}
</StyledTooltip>
</>
)}
</TitleAndIconContainer>
);
};
4 changes: 2 additions & 2 deletions src/components/controls/choose-dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import { connect } from "react-redux";
import { withTranslation } from "react-i18next";
import ChooseDatasetSelect from "./choose-dataset-select";
import { AnnotatedHeader } from "./annotatedHeader";
import { ControlHeader } from "./controlHeader";

// const DroppedFiles = withTheme((props) => {
// /* TODO: this shouldn't be in the auspice src, rather injected as an extension when needed */
Expand Down Expand Up @@ -54,7 +54,7 @@ class ChooseDataset extends React.Component {

return (
<>
<AnnotatedHeader title={t("sidebar:Dataset")} />
<ControlHeader title={t("sidebar:Dataset")} />
{options.map((option, optionIdx) => (
<ChooseDatasetSelect
key={displayedDataset[optionIdx]}
Expand Down
21 changes: 21 additions & 0 deletions src/components/controls/controlHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import { HeaderContainer } from "./styles";
import { AnnotatedTitle, Title, Tooltip } from "./annotatedTitle";

type Props = {
title: Title
tooltip?: Tooltip
}

/**
* A header used by all non-panel controls, containing an informative title.
*/
export const ControlHeader = ({title, tooltip=undefined }: Props) => {
return (
<HeaderContainer>
<AnnotatedTitle
title={title}
tooltip={tooltip} />
</HeaderContainer>
);
};
127 changes: 79 additions & 48 deletions src/components/controls/controls.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import { useSelector } from "react-redux";
import { useTranslation } from 'react-i18next';

import ColorBy, {ColorByInfo} from "./color-by";
Expand All @@ -16,84 +17,114 @@ import GeoResolution from "./geo-resolution";
import TransmissionLines from './transmission-lines';
import NormalizeFrequencies from "./frequency-normalization";
import AnimationOptions from "./animation-options";
import PanelToggles from "./panel-toggles";
import { PanelSection } from "./panelSection";
import ToggleTangle from "./toggle-tangle";
import Language from "./language";
import { ControlsContainer } from "./styles";
import FilterData, {FilterInfo} from "./filter";
import {TreeOptionsInfo, MapOptionsInfo, AnimationOptionsInfo, PanelOptionsInfo,
ExplodeTreeInfo, FrequencyInfo, MeasurementsOptionsInfo} from "./miscInfoText";
import { AnnotatedHeader } from "./annotatedHeader";
import {TreeInfo, MapInfo, AnimationOptionsInfo, PanelLayoutInfo,
ExplodeTreeInfo, EntropyInfo, FrequencyInfo, MeasurementsInfo} from "./miscInfoText";
import { ControlHeader } from "./controlHeader";
import MeasurementsOptions from "./measurementsOptions";
import { RootState } from "../../store";

type Props = {
treeOn: boolean
mapOn: boolean
frequenciesOn: boolean
measurementsOn: boolean
}

function Controls({ treeOn, mapOn, frequenciesOn, measurementsOn }: Props) {
function Controls() {
const { t } = useTranslation();

const panelsAvailable = useSelector((state: RootState) => state.controls.panelsAvailable);
const panelsToDisplay = useSelector((state: RootState) => state.controls.panelsToDisplay);
const showTreeToo = useSelector((state: RootState) => state.controls.showTreeToo);
const canTogglePanelLayout = useSelector((state: RootState) => state.controls.canTogglePanelLayout);

return (
<ControlsContainer>
<ChooseDataset />

<AnnotatedHeader title={t("sidebar:Date Range")} tooltip={DateRangeInfo}/>
<ControlHeader title={t("sidebar:Date Range")} tooltip={DateRangeInfo}/>
<DateRangeInputs />
<AnimationControls />

<AnnotatedHeader title={t("sidebar:Color By")} tooltip={ColorByInfo}/>
<ControlHeader title={t("sidebar:Color By")} tooltip={ColorByInfo}/>
<ColorBy />

<AnnotatedHeader title={t("sidebar:Filter Data")} tooltip={FilterInfo}/>
<FilterData measurementsOn={measurementsOn} />

{treeOn &&
<span>
<AnnotatedHeader title={t("sidebar:Tree Options")} tooltip={TreeOptionsInfo}/>
<ChooseLayout />
<ChooseMetric />
<ChooseBranchLabelling />
<ChooseTipLabel />
<ChooseSecondTree />
<ChooseExplodeAttr tooltip={ExplodeTreeInfo} />
<ToggleTangle />
</span>
<ControlHeader title={t("sidebar:Filter Data")} tooltip={FilterInfo}/>
<FilterData measurementsOn={panelsToDisplay.includes("measurements")} />

<span style={{ paddingTop: "10px" }} />

{panelsAvailable.includes("tree") &&
<PanelSection
panel="tree"
title={t("sidebar:Tree")}
tooltip={TreeInfo}
options={<>
<ChooseLayout />
<ChooseMetric />
<ChooseBranchLabelling />
<ChooseTipLabel />
<ChooseSecondTree />
<ChooseExplodeAttr tooltip={ExplodeTreeInfo} />
<ToggleTangle />
</>}
/>
}

{panelsAvailable.includes("measurements") &&
<PanelSection
panel="measurements"
title={t("sidebar:Measurements")}
tooltip={MeasurementsInfo}
options={<MeasurementsOptions />}
/>
}

{measurementsOn &&
<span style={{ marginTop: "10px" }}>
<AnnotatedHeader title={t("sidebar:Measurements Options")} tooltip={MeasurementsOptionsInfo}/>
<MeasurementsOptions />
</span>
{/* Prevent the map from being toggled on when a second tree is visible.
It is hidden by logic elsewhere.
*/}
{panelsAvailable.includes("map") && !showTreeToo &&
<PanelSection
panel="map"
title={t("sidebar:Map")}
tooltip={MapInfo}
options={<>
<GeoResolution />
<TransmissionLines />
</>}
/>
}

{mapOn &&
<span style={{ marginTop: "10px" }}>
<AnnotatedHeader title={t("sidebar:Map Options")} tooltip={MapOptionsInfo}/>
<GeoResolution />
<TransmissionLines />
</span>
{panelsAvailable.includes("entropy") &&
<PanelSection
panel="entropy"
title={t("sidebar:Entropy")}
tooltip={EntropyInfo}
/>
}

{frequenciesOn &&
<span style={{ marginTop: "10px" }}>
<AnnotatedHeader title={t("sidebar:Frequency Options")} tooltip={FrequencyInfo}/>
<NormalizeFrequencies />
</span>
{panelsAvailable.includes("frequencies") &&
<PanelSection
panel="frequencies"
title={t("sidebar:Frequency")}
tooltip={FrequencyInfo}
options={<NormalizeFrequencies />}
/>
}

<span style={{ marginTop: "10px" }}>
<AnnotatedHeader title={t("sidebar:Animation Options")} tooltip={AnimationOptionsInfo}/>
<ControlHeader title={t("sidebar:Animation Options")} tooltip={AnimationOptionsInfo}/>
<AnimationOptions />
</span>

{canTogglePanelLayout &&
<>
<span style={{ paddingTop: "10px" }} />
<ControlHeader title={t("sidebar:Display")} tooltip={PanelLayoutInfo} />
<PanelLayout />
</>
}

<span style={{ paddingTop: "10px" }} />
<AnnotatedHeader title={t("sidebar:Panel Options")} tooltip={PanelOptionsInfo}/>
<PanelLayout />
<PanelToggles />
<ControlHeader title={t("sidebar:Language")}/>
<Language />
</ControlsContainer>
);
Expand Down
35 changes: 13 additions & 22 deletions src/components/controls/language.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React from "react";
import { connect } from "react-redux";
import { withTranslation } from "react-i18next";
import i18n from "i18next";

import { controlsWidth } from "../../util/globals";
import { analyticsControlsEvent } from "../../util/googleAnalytics";
import { SidebarSubtitle } from "./styles";
import { CHANGE_LANGUAGE } from "../../actions/types";
import CustomSelect from "./customSelect";

Expand Down Expand Up @@ -62,29 +60,22 @@ class Language extends React.Component {
}

render() {
const { t } = this.props;
const selectOptions = this.getlanguageOptions();
return (
<>
<SidebarSubtitle spaceAbove>
{t("sidebar:Language")}
</SidebarSubtitle>
<div style={{paddingBottom: 100, width: controlsWidth, fontSize: 14}}>
<CustomSelect
name="selectLanguage"
id="selectLanguage"
value={selectOptions.filter(({value}) => value === this.props.language)}
options={selectOptions}
isClearable={false}
isSearchable={false}
isMulti={false}
onChange={(opt) => {this.changeLanguage(opt.value);}}
/>
</div>
</>
<div style={{paddingBottom: 100, width: controlsWidth, fontSize: 14}}>
<CustomSelect
name="selectLanguage"
id="selectLanguage"
value={selectOptions.filter(({value}) => value === this.props.language)}
options={selectOptions}
isClearable={false}
isSearchable={false}
isMulti={false}
onChange={(opt) => {this.changeLanguage(opt.value);}}
/>
</div>
);
}
}
const WithTranslation = withTranslation()(Language);

export default WithTranslation;
export default Language;
Loading

0 comments on commit 4e2de85

Please sign in to comment.