Add complete multi-theme dashboard system including: - 8 selectable themes with persistent per-browser preferences - Theme bootstrap script to prevent FOUC on page load - 12+ reusable chart components (area, bar, donut, radial gauge, etc) - Custom checkbox UI component - New settings page for appearance customization Other changes: - Optimize supplier map API payload with getMappableSuppliers helper - Add aria-label attributes to back buttons on detail pages for better accessibility - Update next.config.ts to include new local development IP 192.168.1.128 - Update site manifest with all new favicon and PWA assets - Fix styling and layout spacing in rewrite quote modal
90 lines
3.9 KiB
Markdown
90 lines
3.9 KiB
Markdown
# WFDASH — Multi-theme system
|
|
|
|
Ship 8 selectable themes (5 standard + 3 standout) with a warm/dark mode toggle.
|
|
Theme selection persists per browser. No FOUC on reload.
|
|
|
|
## File map
|
|
|
|
```
|
|
src/
|
|
├── lib/
|
|
│ ├── themes.ts # 8-theme registry (id, label, fonts, swatches)
|
|
│ └── use-theme-id.ts # Client hook to read/write active theme
|
|
├── styles/
|
|
│ └── themes.css # OKLCH token blocks for all 8 themes (warm + dark)
|
|
├── components/
|
|
│ ├── theme-provider.tsx # next-themes wrapper (manages warm/dark mode)
|
|
│ ├── theme-bootstrap.tsx # Inline <head> script — prevents FOUC
|
|
│ ├── theme-picker.tsx # Settings UI — mini preview cards
|
|
│ └── sidebar.tsx # +Settings nav item
|
|
└── app/
|
|
├── layout.tsx # +Inter, Space Grotesk, DM Sans, Playfair,
|
|
│ # Lato, Nunito, Outfit, JetBrains Mono via next/font
|
|
├── globals.css # Imports themes.css
|
|
└── (app)/settings/page.tsx # New Settings page with Appearance section
|
|
```
|
|
|
|
## The 8 themes
|
|
|
|
| # | ID | Category | Fonts | Radius | Notes |
|
|
|---|---|---|---|---|---|
|
|
| 1 | `crisp` | Standard | Inter | 10px | Default. Calm, professional. |
|
|
| 2 | `midnight` | Standard | Space Grotesk + DM Sans | 12px | Dark control-room. |
|
|
| 3 | `editorial` | Standard | Playfair Display + Lato | 6px | Warm cream + serif. |
|
|
| 4 | `bento` | Standard | Inter | 18px | Tinted tiles, big radius. |
|
|
| 5 | `field-ops` | Standard | Inter | 8px | Dense, navy sidebar, gold CTA. |
|
|
| 6 | `terminal` | **Standout** | JetBrains Mono | 0px | Green CRT, scanlines, mono. |
|
|
| 7 | `blueprint` | **Standout** | JetBrains Mono + Inter | 2px | White-on-blue, grid, technical. |
|
|
| 8 | `confetti` | **Standout** | Outfit + Nunito | 20px | Pastel, playful, oversized radius. |
|
|
|
|
## How it works
|
|
|
|
**Theme identity** = `data-theme="<id>"` on `<html>`
|
|
- Set by `theme-bootstrap.tsx` before hydration (prevents flash)
|
|
- Updated by `useThemeId()` hook when user picks a new theme
|
|
- Persisted to `localStorage["wfdash-theme"]`
|
|
|
|
**Mode (warm/dark)** = `.warm` or `.dark` class on `<html>`
|
|
- Managed by `next-themes` (already wired in `theme-provider.tsx`)
|
|
- Persisted to `localStorage["wfdash-mode"]`
|
|
- Independent from theme — you can mix any theme with any mode
|
|
|
|
**shadcn/ui adapts automatically** because all components read from CSS vars
|
|
(`--background`, `--primary`, `--accent`, `--radius`, etc.) that themes.css
|
|
overrides per theme.
|
|
|
|
## How to add a new theme
|
|
|
|
1. Add an entry to `THEMES` in `src/lib/themes.ts`
|
|
2. Add a `[data-theme="<id>"]` block in `src/styles/themes.css` (copy an existing
|
|
theme and adjust tokens). Add `.dark` variant if it works in dark mode.
|
|
3. Add `radiusMap[<id>]` in `theme-bootstrap.tsx`
|
|
4. Done — picker picks it up automatically
|
|
|
|
## How to ship a font swap
|
|
|
|
Each theme has `fontHeading` + `fontBody` pointing at a CSS var. Add the font to
|
|
`src/app/layout.tsx` via `next/font/google` and register its `.variable`. Then
|
|
add the binding in `src/styles/themes.css`:
|
|
|
|
```css
|
|
[data-theme="<id>"] {
|
|
--font-heading: var(--font-<your-font>);
|
|
--font-body: var(--font-<your-font>);
|
|
}
|
|
```
|
|
|
|
The body picks up `var(--font-body)` automatically; `font-heading-theme` class
|
|
applies heading font where you need it.
|
|
|
|
## Standout theme caveats
|
|
|
|
The 3 standout themes override default component styling:
|
|
|
|
- **Terminal** — sharp 0px radius, uppercase headings, mono everywhere, scanline body overlay
|
|
- **Blueprint** — sharp 2px radius, uppercase headings, grid overlay, transparent inputs
|
|
- **Confetti** — 20px radius (capped — shadcn's `--radius-4xl` calc clamps at ~1.6rem)
|
|
|
|
All three are still built on the brand palette (#4C96D7 / #F2AF58 / #E94E49) but
|
|
applied in different ways. They're tested against the standard shadcn components
|
|
but may render slightly differently from the 5 standard themes — by design.
|