- Refactored TimerPage component to improve layout and user experience. - Updated theme configuration to utilize design tokens for better maintainability. - Introduced new tokens for colors and typography to align with design principles. - Simplified state management and improved timer functionality. - Enhanced accessibility and responsiveness of UI elements.
63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
/**
|
|
* Chart colours.
|
|
*
|
|
* These are the validated data-viz slots, not the brand accent: the UI is warm
|
|
* ember on paper, but a chart has to stay readable for colour-blind readers in
|
|
* both themes, so identity colours come from the reference palette. Focus takes
|
|
* the orange slot (nearest the brand's warmth), breaks take aqua, and anything
|
|
* that encodes *magnitude* uses the single-hue blue ramp — this ordering was run
|
|
* through the palette validator for all pairs in both modes.
|
|
*/
|
|
|
|
export interface VizPalette {
|
|
work: string;
|
|
shortBreak: string;
|
|
longBreak: string;
|
|
sequential: string[];
|
|
grid: string;
|
|
axis: string;
|
|
empty: string;
|
|
}
|
|
|
|
const LIGHT: VizPalette = {
|
|
work: "#eb6834",
|
|
shortBreak: "#2a78d6",
|
|
longBreak: "#1baf7a",
|
|
// blue 100 → 600: "more pomodoros" reads as "darker".
|
|
sequential: ["#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf", "#184f95"],
|
|
grid: "rgba(23, 21, 15, 0.12)",
|
|
axis: "rgba(23, 21, 15, 0.45)",
|
|
empty: "rgba(23, 21, 15, 0.07)",
|
|
};
|
|
|
|
const DARK: VizPalette = {
|
|
work: "#d95926",
|
|
shortBreak: "#3987e5",
|
|
longBreak: "#199e70",
|
|
sequential: ["#104281", "#184f95", "#256abf", "#3987e5", "#6da7ec", "#9ec5f4"],
|
|
grid: "rgba(244, 241, 234, 0.14)",
|
|
axis: "rgba(244, 241, 234, 0.55)",
|
|
empty: "rgba(244, 241, 234, 0.08)",
|
|
};
|
|
|
|
export function vizPalette(dark: boolean): VizPalette {
|
|
return dark ? DARK : LIGHT;
|
|
}
|
|
|
|
export function kindColor(kind: string, palette: VizPalette): string {
|
|
if (kind === "work") return palette.work;
|
|
if (kind === "long_break") return palette.longBreak;
|
|
return palette.shortBreak;
|
|
}
|
|
|
|
/** Pick a ramp step for a count; null means "nothing happened". */
|
|
export function rampStep(count: number, goal: number, palette: VizPalette): string | null {
|
|
if (count <= 0) return null;
|
|
const ratio = goal > 0 ? count / goal : count / 8;
|
|
const index = Math.min(
|
|
palette.sequential.length - 1,
|
|
Math.max(0, Math.round(ratio * (palette.sequential.length - 1))),
|
|
);
|
|
return palette.sequential[index];
|
|
}
|