SelectControl: 32px trigger scale + option-group divider in the theme picker

This commit is contained in:
2026-06-12 21:46:53 +03:00
parent ca70b3e491
commit d1ba921141
8 changed files with 136 additions and 30 deletions
+12 -1
View File
@@ -171,7 +171,18 @@ describe('custom theme selections', () => {
expect(options[2].label).toBe('Brand');
});
it('marks the roster boundary on the first preset, wherever the customs end', () => {
for (const customs of [[], themes]) {
const options = chartThemeOptions(customs);
const dividers = options.filter((o) => o.dividerBefore);
expect(dividers).toHaveLength(1);
expect(dividers[0].value).toBe(CHART_THEME_OPTIONS[2].value); // first preset
expect(options.indexOf(dividers[0])).toBe(2 + customs.length);
}
});
it('lists no custom entries when the library has none', () => {
expect(chartThemeOptions([])).toEqual([...CHART_THEME_OPTIONS]);
const values = chartThemeOptions([]).map((o) => o.value);
expect(values).toEqual(CHART_THEME_OPTIONS.map((o) => o.value));
});
});
+19 -3
View File
@@ -191,6 +191,12 @@ export interface ChartThemeOption {
label: string;
/** Secondary line for pickers (what the choice means). */
detail?: string;
/**
* Group boundary: this option starts the preset roster, visually separated
* from the built-ins and the user's themes above it. Set here, where the list
* order is decided — consumers must never recompute the boundary by index.
*/
dividerBefore?: boolean;
}
/** Display metadata for every selectable chart theme, in display order. */
@@ -252,7 +258,9 @@ export function isChartThemeSelection(value: unknown): value is ChartThemeSelect
/**
* The full picker option list: built-ins, the user's saved themes (by name, in
* library order), then the presets. Pure derivation — callers memoize.
* library order), then the presets — with the first preset carrying the group
* divider that bounds "ours" from the imported roster. Pure derivation —
* callers memoize.
*/
export function chartThemeOptions(
customThemes: ReadonlyArray<Pick<CustomTheme, 'id' | 'name'>>,
@@ -262,8 +270,16 @@ export function chartThemeOptions(
label: t.name,
detail: 'Custom theme',
}));
// Built-ins first, the user's own themes next, the preset roster last.
return [...CHART_THEME_OPTIONS.slice(0, 2), ...custom, ...CHART_THEME_OPTIONS.slice(2)];
// Built-ins first, the user's own themes next, the preset roster last. The
// divider rides on the first preset option itself, so it stays correct however
// a consumer splices into the list (e.g. the picker's "Edit themes…" row).
const [firstPreset, ...presets] = CHART_THEME_OPTIONS.slice(2);
return [
...CHART_THEME_OPTIONS.slice(0, 2),
...custom,
{ ...firstPreset, dividerBefore: true },
...presets,
];
}
/**