Sidebar improvements (Collapse/Expand, Mobile view) (#215)

* Extract sidebar to new component

* Add sidebar toggle

* Fix scrollbars sometimes appearing even at maximum zoom-out
This commit is contained in:
czifumasa
2025-09-09 10:41:45 +02:00
committed by GitHub
parent 0f0a75a5ec
commit 2a0c963789
15 changed files with 272 additions and 77 deletions

View File

@@ -3,9 +3,14 @@ import queryString from 'query-string';
import {useEffect, useState} from 'react';
import {FormattedMessage, useIntl} from 'react-intl';
import {Navigate, Route, Routes, useLocation, useNavigate} from 'react-router';
import {Loader, Message, Portal, Tab} from 'semantic-ui-react';
import {
Loader,
Message,
Portal,
SidebarPushable,
SidebarPusher,
} from 'semantic-ui-react';
import {IndiInfo} from 'topola';
import {Changelog} from './changelog';
import {
Chart,
ChartType,
@@ -14,15 +19,6 @@ import {
downloadSvg,
printChart,
} from './chart';
import {
argsToConfig,
Config,
ConfigPanel,
configToArgs,
DEFALUT_CONFIG,
Ids,
Sex,
} from './config';
import {DataSourceEnum, SourceSelection} from './datasource/data_source';
import {EmbeddedDataSource, EmbeddedSourceSpec} from './datasource/embedded';
import {
@@ -38,14 +34,21 @@ import {
WikiTreeDataSource,
WikiTreeSourceSpec,
} from './datasource/wikitree';
import {Details} from './details/details';
import {DonatsoChart} from './donatso-chart';
import {Intro} from './intro';
import {TopBar} from './menu/top_bar';
import {
argsToConfig,
Config,
configToArgs,
DEFALUT_CONFIG,
Ids,
Sex,
} from './sidepanel/config/config';
import {SidePanel} from './sidepanel/side-panel';
import {analyticsEvent} from './util/analytics';
import {getI18nMessage} from './util/error_i18n';
import {idToIndiMap, TopolaData} from './util/gedcom_util';
import {Media} from './util/media';
/**
* Load GEDCOM URL from VITE_STATIC_URL environment variable.
@@ -241,7 +244,7 @@ export function App() {
}
}
function toggleDetails(config: Config, data: TopolaData | undefined) {
function updateChartWithConfig(config: Config, data: TopolaData | undefined) {
if (data === undefined) {
return;
}
@@ -254,6 +257,14 @@ export function App() {
});
}
function onToggleSidePanel() {
const newShowSidePanel = !showSidePanel;
setShowSidePanel(newShowSidePanel);
updateUrl({
sidePanel: newShowSidePanel ? 'true' : 'false',
});
}
/** Sets error message after data load failure. */
function setErrorMessage(message: string) {
setError(message);
@@ -362,7 +373,7 @@ export function App() {
const data = await loadData(args.sourceSpec, args.selection);
// Set state with data.
setData(data);
toggleDetails(args.config, data);
updateChartWithConfig(args.config, data);
setShowSidePanel(args.showSidePanel);
setState(AppState.SHOWING_CHART);
} catch (error: any) {
@@ -510,33 +521,6 @@ export function App() {
case AppState.SHOWING_CHART:
case AppState.LOADING_MORE:
const updatedSelection = getSelection(data!.chartData, selection);
const sidePanelTabs = [
{
menuItem: intl.formatMessage({
id: 'tab.info',
defaultMessage: 'Info',
}),
render: () => (
<Details gedcom={data!.gedcom} indi={updatedSelection.id} />
),
},
{
menuItem: intl.formatMessage({
id: 'tab.settings',
defaultMessage: 'Settings',
}),
render: () => (
<ConfigPanel
config={config}
onChange={(config) => {
setConfig(config);
toggleDetails(config, data);
updateUrl(configToArgs(config));
}}
/>
),
},
];
return (
<div id="content">
<ErrorPopup
@@ -547,13 +531,21 @@ export function App() {
{state === AppState.LOADING_MORE ? (
<Loader active size="small" className="loading-more" />
) : null}
{renderChart(updatedSelection)}
{showSidePanel ? (
<Media greaterThanOrEqual="large" className="sidePanel">
<Tab panes={sidePanelTabs} />
</Media>
) : null}
<Changelog />
<SidebarPushable>
<SidePanel
data={data!}
selectedIndiId={updatedSelection.id}
config={config}
expanded={showSidePanel}
onToggle={onToggleSidePanel}
onConfigChange={(config) => {
setConfig(config);
updateChartWithConfig(config, data);
updateUrl(configToArgs(config));
}}
/>
<SidebarPusher>{renderChart(updatedSelection)}</SidebarPusher>
</SidebarPushable>
</div>
);