feat(quick-261016-0fm): manual theme switch on the rail
- the rail's top button cycles system, light and dark and names the current choice; light and dark ignore prefers-color-scheme - usePreferences applies the cached theme before the first await of boot, saves the choice through PUT /account/preferences and reverts with a toast when the save fails; me() applies the stored preference
This commit is contained in:
@@ -1,15 +1,32 @@
|
||||
// Colour scheme (D-06, flagged assumption A6): the admin follows the system
|
||||
// preference only, with no toggle. The .dark class on the document element
|
||||
// swaps the design's dark tokens in main.css; the sidebar stays dark in both
|
||||
// modes and gains its #222b40 right border in dark mode.
|
||||
// Colour scheme (D-06; assumption A6 superseded). The admin follows the
|
||||
// system preference by default; light and dark are manual choices the admin
|
||||
// makes on the rail's top button and keeps per account (usePreferences). The
|
||||
// .dark class on the document element swaps the design's dark tokens in
|
||||
// main.css; the sidebar stays dark in both modes and gains its #222b40 right
|
||||
// border in dark mode.
|
||||
export const DARK_QUERY = '(prefers-color-scheme: dark)'
|
||||
|
||||
/** The admin's theme: follow the system, or always light or dark. */
|
||||
export type ThemeChoice = 'system' | 'light' | 'dark'
|
||||
|
||||
/** The theme choices in the order the rail button cycles through them. */
|
||||
export const THEME_CHOICES: readonly ThemeChoice[] = ['system', 'light', 'dark']
|
||||
|
||||
export function isThemeChoice(value: unknown): value is ThemeChoice {
|
||||
return typeof value === 'string' && (THEME_CHOICES as readonly string[]).includes(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the current preference and follows changes. Returns the
|
||||
* unsubscribe function.
|
||||
* Applies a theme choice. light and dark set the class once and subscribe
|
||||
* to nothing; system applies the current preference and follows changes.
|
||||
* Returns the unsubscribe function.
|
||||
*/
|
||||
export function applyColorScheme(win: Window = window): () => void {
|
||||
export function applyColorScheme(win: Window = window, choice: ThemeChoice = 'system'): () => void {
|
||||
const root = win.document.documentElement
|
||||
if (choice !== 'system') {
|
||||
root.classList.toggle('dark', choice === 'dark')
|
||||
return () => undefined
|
||||
}
|
||||
if (typeof win.matchMedia !== 'function') {
|
||||
root.classList.remove('dark')
|
||||
return () => undefined
|
||||
|
||||
Reference in New Issue
Block a user