mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 18:48:11 +00:00
67 lines
2.3 KiB
TypeScript
67 lines
2.3 KiB
TypeScript
/**
|
|
* Chart palette.
|
|
*
|
|
* Categorical slots are assigned in fixed order and never cycled — a series keeps its
|
|
* hue when a filter removes its neighbours. Both modes are separately stepped for their
|
|
* own surface, not an automatic flip of the light values.
|
|
*
|
|
* Validated against this app's card surfaces (light `#ffffff`, dark `#0f1729`) with the
|
|
* dataviz six-check validator, six slots, adjacent pairlist:
|
|
* light — CVD ΔE 9.1, normal-vision ΔE 19.6, contrast WARN on aqua/yellow/magenta
|
|
* dark — CVD ΔE 8.4, normal-vision ΔE 19.3, contrast all ≥ 3:1
|
|
* The light-mode contrast WARN obliges *relief*: every chart using these slots ships a
|
|
* legend with visible text labels and a table view of the same numbers.
|
|
*/
|
|
|
|
export interface ChartPalette {
|
|
/** Categorical slots, in fixed assignment order. */
|
|
categorical: readonly string[];
|
|
/** Single hue for magnitude — one colour for every bar in a one-series chart. */
|
|
sequential: string;
|
|
/** Recessive chrome. */
|
|
grid: string;
|
|
axis: string;
|
|
/** Text tokens — labels never wear the data colour. */
|
|
textMuted: string;
|
|
/** Surface, for the 2px gaps and rings that separate marks. */
|
|
surface: string;
|
|
tooltipBg: string;
|
|
tooltipBorder: string;
|
|
}
|
|
|
|
const LIGHT: ChartPalette = {
|
|
categorical: ['#2a78d6', '#eb6834', '#1baf7a', '#eda100', '#e87ba4', '#008300'],
|
|
sequential: '#2a78d6',
|
|
grid: '#e1e0d9',
|
|
axis: '#c3c2b7',
|
|
textMuted: '#898781',
|
|
surface: '#ffffff',
|
|
tooltipBg: '#ffffff',
|
|
tooltipBorder: 'rgba(11,11,11,0.10)',
|
|
};
|
|
|
|
const DARK: ChartPalette = {
|
|
categorical: ['#3987e5', '#d95926', '#199e70', '#c98500', '#d55181', '#008300'],
|
|
sequential: '#3987e5',
|
|
grid: '#2c2c2a',
|
|
axis: '#383835',
|
|
textMuted: '#898781',
|
|
surface: '#0f1729',
|
|
tooltipBg: '#0f1729',
|
|
tooltipBorder: 'rgba(255,255,255,0.10)',
|
|
};
|
|
|
|
export function getChartPalette(isDark: boolean): ChartPalette {
|
|
return isDark ? DARK : LIGHT;
|
|
}
|
|
|
|
/**
|
|
* Colour for a categorical member, keyed by its position in a **stable** ordering of the
|
|
* whole domain — never by its rank in the current filtered view, so filtering does not
|
|
* repaint the survivors. Past the last slot everything folds into one neutral bucket
|
|
* rather than inventing a hue no CVD check would pass.
|
|
*/
|
|
export function categoricalColor(palette: ChartPalette, index: number): string {
|
|
return palette.categorical[index] ?? palette.textMuted;
|
|
}
|