mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Theme Builder: accordion panels across the full config surface, vertical-tab nav, reflective gallery
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Theme Builder — Headers panel (docs/chart-theming-scope.md §5).
|
||||
*
|
||||
* The base facet-header config (`config.header.*`) — the titles and labels that
|
||||
* caption each panel of a faceted chart (the `row`/`column`/`facet` channels).
|
||||
* The per-position variants (`headerRow`, `headerColumn`, `headerFacet`) stay in
|
||||
* the JSON; this is the common surface a brand tunes. Each control writes a
|
||||
* minimal diff through the shared setter.
|
||||
*/
|
||||
|
||||
import type { JsonObject } from '@core/spec-config';
|
||||
import {
|
||||
asNumber,
|
||||
asString,
|
||||
type ConfigPath,
|
||||
countSet,
|
||||
getConfigValue,
|
||||
} from '@core/theme-controls';
|
||||
import { useConfigSetter } from '../stores/CustomThemeStore';
|
||||
import { Accordion, type AccordionSection, ColorRow, NumberRow, WeightRow } from './ThemeFields';
|
||||
|
||||
const TEXT_GREY = '#888888';
|
||||
|
||||
const TITLE_COLOR: ConfigPath = ['header', 'titleColor'];
|
||||
const TITLE_SIZE: ConfigPath = ['header', 'titleFontSize'];
|
||||
const TITLE_WEIGHT: ConfigPath = ['header', 'titleFontWeight'];
|
||||
const LABEL_COLOR: ConfigPath = ['header', 'labelColor'];
|
||||
const LABEL_SIZE: ConfigPath = ['header', 'labelFontSize'];
|
||||
const LABEL_WEIGHT: ConfigPath = ['header', 'labelFontWeight'];
|
||||
|
||||
export function HeaderControls({ config }: { config: JsonObject }) {
|
||||
const set = useConfigSetter();
|
||||
|
||||
const sections: AccordionSection[] = [
|
||||
{
|
||||
id: 'titles',
|
||||
title: 'Facet titles',
|
||||
hint: "The caption naming each facet's field.",
|
||||
badge: countSet(config, [TITLE_COLOR, TITLE_SIZE, TITLE_WEIGHT]),
|
||||
children: (
|
||||
<>
|
||||
<ColorRow
|
||||
label="Color"
|
||||
name="Header title color"
|
||||
value={asString(getConfigValue(config, TITLE_COLOR))}
|
||||
fallback={TEXT_GREY}
|
||||
onChange={(hex) => set(TITLE_COLOR, hex)}
|
||||
onClear={() => set(TITLE_COLOR, undefined)}
|
||||
/>
|
||||
<NumberRow
|
||||
label="Size"
|
||||
name="Header title size"
|
||||
value={asNumber(getConfigValue(config, TITLE_SIZE))}
|
||||
min={0}
|
||||
unit="px"
|
||||
onChange={(n) => set(TITLE_SIZE, n)}
|
||||
/>
|
||||
<WeightRow
|
||||
id="header-title-weight"
|
||||
label="Weight"
|
||||
name="Header title weight"
|
||||
value={getConfigValue(config, TITLE_WEIGHT)}
|
||||
onChange={(w) => set(TITLE_WEIGHT, w)}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'labels',
|
||||
title: 'Facet labels',
|
||||
hint: 'The per-panel value labels.',
|
||||
badge: countSet(config, [LABEL_COLOR, LABEL_SIZE, LABEL_WEIGHT]),
|
||||
children: (
|
||||
<>
|
||||
<ColorRow
|
||||
label="Color"
|
||||
name="Header label color"
|
||||
value={asString(getConfigValue(config, LABEL_COLOR))}
|
||||
fallback={TEXT_GREY}
|
||||
onChange={(hex) => set(LABEL_COLOR, hex)}
|
||||
onClear={() => set(LABEL_COLOR, undefined)}
|
||||
/>
|
||||
<NumberRow
|
||||
label="Size"
|
||||
name="Header label size"
|
||||
value={asNumber(getConfigValue(config, LABEL_SIZE))}
|
||||
min={0}
|
||||
unit="px"
|
||||
onChange={(n) => set(LABEL_SIZE, n)}
|
||||
/>
|
||||
<WeightRow
|
||||
id="header-label-weight"
|
||||
label="Weight"
|
||||
name="Header label weight"
|
||||
value={getConfigValue(config, LABEL_WEIGHT)}
|
||||
onChange={(w) => set(LABEL_WEIGHT, w)}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return <Accordion sections={sections} idPrefix="headers" />;
|
||||
}
|
||||
Reference in New Issue
Block a user