refactor: enhance TimerPage layout and functionality; update theme and tokens for improved design consistency
- 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.
This commit is contained in:
84 files changed
+4501
-2682
No files matched your search
@@ -27,6 +27,7 @@ export const KIND_LABEL: Record<string, string> = {
|
||||
export const BUCKET_LABEL: Record<string, string> = {
|
||||
overdue: "Overdue",
|
||||
today: "Due today",
|
||||
active: "Would be nice to start",
|
||||
upcoming: "Coming up",
|
||||
someday: "No deadline",
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface TimerState {
|
||||
finished?: TimerSession | null;
|
||||
auto_started?: TimerSession | null;
|
||||
celebration?: string | null;
|
||||
timer_enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface Task {
|
||||
@@ -50,7 +51,7 @@ export interface Task {
|
||||
stale: boolean;
|
||||
estimated_pomodoros: number | null;
|
||||
days_overdue: number;
|
||||
bucket: "overdue" | "today" | "upcoming" | "someday";
|
||||
bucket: "overdue" | "today" | "active" | "upcoming" | "someday";
|
||||
}
|
||||
|
||||
export interface TaskListResponse {
|
||||
@@ -64,11 +65,21 @@ export interface RefreshResult {
|
||||
refreshed_at: string;
|
||||
date: string;
|
||||
total: number;
|
||||
sources: { source: string; label: string; ok: boolean; error: string | null; count: number }[];
|
||||
closed: number;
|
||||
sources: {
|
||||
source: string;
|
||||
label: string;
|
||||
ok: boolean;
|
||||
error: string | null;
|
||||
count: number;
|
||||
/** How many tasks this refresh found closed in that tool. */
|
||||
closed?: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface BlockerPolicy {
|
||||
active: boolean;
|
||||
unexpandable?: string[];
|
||||
reason: string;
|
||||
mode: string;
|
||||
enabled: boolean;
|
||||
@@ -165,12 +176,13 @@ export interface AppSettings {
|
||||
alarm_sound: boolean;
|
||||
alarm_volume: number;
|
||||
desktop_notifications: boolean;
|
||||
timer_enabled: boolean;
|
||||
keep_on_top_during_work: boolean;
|
||||
};
|
||||
sources: {
|
||||
jira: Record<string, unknown> & { enabled: boolean; base_url: string; email: string; api_token: string; extra_jql: string; start_date_field: string; include_all_open: boolean; writeback_done: boolean; done_transition_name: string; max_issues: number };
|
||||
google_tasks: { enabled: boolean; client_id: string; client_secret: string; refresh_token: string; lists: string[]; include_undated: boolean; writeback_done: boolean };
|
||||
todoist: { enabled: boolean; api_token: string; projects: string[]; filter_query: string; writeback_done: boolean };
|
||||
jira: Record<string, unknown> & { enabled: boolean; base_url: string; email: string; api_token: string; extra_jql: string; start_date_field: string; include_all_open: boolean; max_issues: number };
|
||||
google_tasks: { enabled: boolean; client_id: string; client_secret: string; refresh_token: string; lists: string[]; include_undated: boolean };
|
||||
todoist: { enabled: boolean; api_token: string; projects: string[]; filter_query: string };
|
||||
laundry: { enabled: boolean; base_url: string; session_cookie: string };
|
||||
refresh_interval_minutes: number;
|
||||
request_timeout_seconds: number;
|
||||
@@ -181,6 +193,7 @@ export interface AppSettings {
|
||||
block_during_breaks: boolean;
|
||||
blocked_domains: string[];
|
||||
allowed_domains: string[];
|
||||
subdomain_expansions: string[];
|
||||
blocked_apps: string[];
|
||||
kill_blocked_apps: boolean;
|
||||
schedule: { label: string; start: string; end: string; days: number[] }[];
|
||||
|
||||
+23
-18
@@ -1,10 +1,12 @@
|
||||
/**
|
||||
* Chart colours.
|
||||
*
|
||||
* These are the validated data-viz slots, not the Material theme's palette: the
|
||||
* UI's accent can be anything, but a chart has to stay readable for colour-blind
|
||||
* readers in both themes. Work/short/long are categorical slots 1–3 (validated
|
||||
* all-pairs in both modes); magnitude charts use the single-hue blue ramp.
|
||||
* 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 {
|
||||
@@ -14,28 +16,28 @@ export interface VizPalette {
|
||||
sequential: string[];
|
||||
grid: string;
|
||||
axis: string;
|
||||
surface: string;
|
||||
empty: string;
|
||||
}
|
||||
|
||||
const LIGHT: VizPalette = {
|
||||
work: "#2a78d6",
|
||||
shortBreak: "#eb6834",
|
||||
work: "#eb6834",
|
||||
shortBreak: "#2a78d6",
|
||||
longBreak: "#1baf7a",
|
||||
// blue 100 → 600, light → dark: "more pomodoros" reads as "darker".
|
||||
// blue 100 → 600: "more pomodoros" reads as "darker".
|
||||
sequential: ["#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf", "#184f95"],
|
||||
grid: "rgba(0,0,0,0.08)",
|
||||
axis: "rgba(0,0,0,0.45)",
|
||||
surface: "#fcfcfb",
|
||||
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: "#3987e5",
|
||||
shortBreak: "#d95926",
|
||||
work: "#d95926",
|
||||
shortBreak: "#3987e5",
|
||||
longBreak: "#199e70",
|
||||
sequential: ["#104281", "#184f95", "#256abf", "#3987e5", "#6da7ec", "#9ec5f4"],
|
||||
grid: "rgba(255,255,255,0.10)",
|
||||
axis: "rgba(255,255,255,0.55)",
|
||||
surface: "#1a1a19",
|
||||
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 {
|
||||
@@ -48,10 +50,13 @@ export function kindColor(kind: string, palette: VizPalette): string {
|
||||
return palette.shortBreak;
|
||||
}
|
||||
|
||||
/** Pick a ramp step for a count, 0 meaning "empty". */
|
||||
/** 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))));
|
||||
const index = Math.min(
|
||||
palette.sequential.length - 1,
|
||||
Math.max(0, Math.round(ratio * (palette.sequential.length - 1))),
|
||||
);
|
||||
return palette.sequential[index];
|
||||
}
|
||||
Reference in new issue
Block a user