Phase 2 — Theme provider & dark mode
Tasks
Acceptance
- Mount
<ThemeProvider> at root + drop <ThemeToggle /> anywhere → dark mode works everywhere, no FOUC
- Playwright test confirms no theme flash on first paint
- Brand overrides applied by a consumer change the look of all shadcn primitives without touching component code
Depends on Phase 1 (tokens must exist).
Part of the next-shell app shell extraction plan.
Phase 2 — Theme provider & dark mode
Tasks
ThemeProviderwrappingnext-themeswith sensible defaults (class strategy, system default, no-flash)useTheme()hook re-export with typed theme union ("light" | "dark" | "system")ThemeTogglecomponent — icon button variant + dropdown variant — using only semantic tokens{ primary, accent, radius, ...overrides }viaThemeProviderprops → applied as CSS variable overrides on:root/[data-theme="dark"]Acceptance
<ThemeProvider>at root + drop<ThemeToggle />anywhere → dark mode works everywhere, no FOUCDepends on Phase 1 (tokens must exist).
Part of the
next-shellapp shell extraction plan.