69 lines
2.6 KiB
Markdown
69 lines
2.6 KiB
Markdown
## Context
|
|
|
|
The current UI defaults to dark presentation and lacks a global theme control. Users with different preference and accessibility needs cannot choose light/system/high-contrast alternatives.
|
|
|
|
This change introduces an icon-based theme switcher and persistent client-side preference restoration.
|
|
|
|
## Goals / Non-Goals
|
|
|
|
**Goals:**
|
|
- Add a header theme switcher with system, light, dark, and high-contrast options.
|
|
- Apply theme choice globally with minimal visual regression.
|
|
- Persist preference in localStorage with cookie fallback.
|
|
- Restore returning-user choice; default to system when unset.
|
|
|
|
**Non-Goals:**
|
|
- Server-side profile theme persistence.
|
|
- Theme-specific content changes.
|
|
- Full design-system rewrite.
|
|
|
|
## Decisions
|
|
|
|
### Decision: Centralize theme state on `document.documentElement`
|
|
**Decision:** Set a root theme attribute/class and drive color tokens from CSS variables.
|
|
|
|
**Rationale:**
|
|
- Single source of truth for whole page styling.
|
|
- Works with existing Tailwind utility classes via custom CSS variable bridge.
|
|
|
|
**Alternatives considered:**
|
|
- Component-level theming flags: rejected due to drift and maintenance overhead.
|
|
|
|
### Decision: Keep system mode dynamic via `prefers-color-scheme`
|
|
**Decision:** For `system`, listen to media query changes and update resolved theme automatically.
|
|
|
|
**Rationale:**
|
|
- Matches user OS preference behavior.
|
|
|
|
**Alternatives considered:**
|
|
- One-time system snapshot: rejected as surprising for users changing OS theme at runtime.
|
|
|
|
### Decision: Use icon-only options with accessible labels
|
|
**Decision:** Theme controls are icon buttons with ARIA labels and visible selected state.
|
|
|
|
**Rationale:**
|
|
- Meets UX requirement while preserving accessibility.
|
|
|
|
**Alternatives considered:**
|
|
- Text dropdown: rejected due to explicit icon requirement.
|
|
|
|
## Risks / Trade-offs
|
|
|
|
- **[Risk] Existing hardcoded color classes may not adapt perfectly** -> Mitigation: prioritize core surfaces/text and progressively map remaining variants.
|
|
- **[Risk] High-contrast mode may expose layout artifacts** -> Mitigation: audit focus outlines, borders, and semantic contrast first.
|
|
- **[Trade-off] Additional JS for persistence and media listeners** -> Mitigation: keep logic modular and lightweight.
|
|
|
|
## Migration Plan
|
|
|
|
1. Add theme tokens and root theme resolver.
|
|
2. Implement icon switcher in header and state persistence.
|
|
3. Wire system preference listener and fallback behavior.
|
|
4. Validate across refresh/returning sessions and responsive breakpoints.
|
|
|
|
Rollback:
|
|
- Remove theme switcher and resolver, revert to existing dark-default classes.
|
|
|
|
## Open Questions
|
|
|
|
- Should high-contrast mode align with OS `prefers-contrast` in a later phase?
|