Skip to content

Commit 07786a0

Browse files
authored
feat(admin): add light theme appearance preferences (CoreBunch#147)
1 parent c0087ec commit 07786a0

23 files changed

Lines changed: 628 additions & 63 deletions

docs/design.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The design is a **two-layer color model**: an achromatic base (surfaces, borders
1313
- **Bordered transparent inputs.** Inputs have a 1px white-alpha border, transparent background, and a pill 1em radius. Focus adds an inset achromatic glow.
1414
- **Floating overlay panels.** Spotlight, popovers, and modals use direct globals: `--bg-surface`, `--overlay-10`, `--panel-radius`, `--panel-blur`, and `--shadow-panel`.
1515
- **Editor controls** (toolbar buttons, chips) use `--radius` (6px) for default and `--radius-sm` (3px) for tight badges.
16+
- **Admin appearance is token-scoped.** Settings → Preferences stores `theme`, `density`, and `textScale` in `instatic-editor-prefs`; `useEditorAppearancePreferences()` mirrors them to `data-editor-theme`, `data-editor-density`, and `data-editor-text-scale` on the document and layout roots. Light mode and text scaling are token overrides, not per-component restyles.
1617
- **One source of truth: `src/styles/globals.css`.** No hardcoded hex / rgb / hsl in admin / ui CSS modules — gated by `css-token-policy.test.ts`. Admin font sizes use the fluid `--text-*` scale, and admin spacing uses the fluid `--space-*` scale — gated by `admin-typography-token-policy.test.ts` and `admin-spacing-token-policy.test.ts`.
1718
- **CSS Modules only.** No Tailwind utility classes — gated by `noTailwindUtilities.test.ts`. No Tailwind ecosystem deps — gated by `no-tailwind-deps.test.ts`.
1819
- **Every interactive control goes through a UI primitive** from `src/ui/components/`. Bare `<button>` is gated.
@@ -24,7 +25,7 @@ The design is a **two-layer color model**: an achromatic base (surfaces, borders
2425

2526
### 1. The base disappears, the meaning appears
2627

27-
The chrome is dark, neutral, and quiet so the user's content and the system's signals are the only things competing for attention. Surfaces, borders, default text — all achromatic. Color is reserved for things that mean something: a green dot says "saved", a peach widget header says "this card is about posts", a neon ring says "the canvas selected this node".
28+
The chrome is neutral and quiet so the user's content and the system's signals are the only things competing for attention. The default theme is dark; the light theme swaps the achromatic base tokens and remaps identity accents to foreground-safe variants while preserving the same hierarchy. Surfaces, borders, default text — all achromatic. Color is reserved for things that mean something: a green dot says "saved", a peach widget header says "this card is about posts", a neon ring says "the canvas selected this node".
2829

2930
If a color isn't carrying information, it doesn't belong in the chrome.
3031

@@ -53,13 +54,12 @@ The base layer uses six surface tones to convey depth without shadows or gradien
5354
--bg-body #000000 ← page bottom (root, behind everything)
5455
--bg-surface #1b1b1b ← darker parent of tile cards / sidebar fill
5556
--bg-surface-2 #282828 ← tile cards themselves, panel bodies
56-
--bg-surface-3 #323232 ← hover state for tiles, nested controls
57-
--bg-surface-4 #4a4a4a ← active state
58-
--bg-surface-5 #605f5f ← active + focused
59-
--bg-surface-3 #323232 ← hover state, nested controls, chips
57+
--bg-surface-3 #323232 ← tile/card hover, nested structural surfaces
58+
--bg-surface-4 #4a4a4a ← stronger nested structural surface
59+
--bg-surface-5 #605f5f ← strongest nested structural surface
6060
```
6161

62-
Hover and active states change **tone**, not border. Reach for the closest tone above the current surface; skip levels only with intent.
62+
Tile/card hovers change **tone**, not border. Compact interactive chrome — buttons, segmented controls, toolbar chips, selected rows, and pressed states — uses the foreground overlay scale (`--overlay-5/10/20/30`) instead of surface steps so the same state hierarchy has enough contrast in both dark and light themes.
6363

6464
### 4. Cards are tiles, not boxes
6565

@@ -100,7 +100,7 @@ Categories of things have an associated color drawn from the numbered **accent**
100100
| `--accent-9` | `#f0a6ff` | Secondary violet identity tint |
101101
| `--accent-10` | `#ff9f9f` | Secondary red identity tint |
102102

103-
Accent tokens don't live in `src/styles/globals.css` to be decorative — they're part of the design system. Panel rails assign these accents automatically using `assignRailAccents` (multi-item surfaces, avoids repeats inside the visible group) or `railAccent` (single item) from `src/ui/railAccent.ts`. Primitives like `Widget` can still accept an explicit tint when the category is product-defined. New identity colors are added by extending the `--accent-*` group, not by inlining a color.
103+
Accent tokens don't live in `src/styles/globals.css` to be decorative — they're part of the design system. Panel rails assign these accents automatically using `assignRailAccents` (multi-item surfaces, avoids repeats inside the visible group) or `railAccent` (single item) from `src/ui/railAccent.ts`. Primitives like `Widget` can still accept an explicit tint when the category is product-defined. The light theme overrides the same accent names with darker foreground colors so rail icons and badges keep contrast on white surfaces. New identity colors are added by extending the `--accent-*` group, not by inlining a color.
104104

105105
### 7. The canvas owns its own palette
106106

@@ -151,7 +151,7 @@ Fluid admin spacing scale:
151151
--space-6xl, --space-7xl, --space-8xl, --space-9xl,
152152
--space-10xl, --space-11xl, --space-12xl
153153
154-
Overlay scale (white alpha):
154+
Overlay scale (foreground alpha; white in dark theme, dark in light theme):
155155
--overlay, --overlay-5, --overlay-10, --overlay-20, --overlay-30,
156156
--overlay-40, --overlay-50, --overlay-60, --overlay-70, --overlay-80,
157157
--overlay-90

docs/e2e/feature-matrix.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ ADMIN-002 note: display-name editing and mobile step-up cancel/no-op are automat
6161

6262
ADMIN-003 note: `admin-navigation.e2e.ts` now verifies the global toolbar trailer on Dashboard, account menu actions, Open Live root fallback, Content selected-entry deep-linking to `/posts/<slug>`, clearing the entry target after leaving Content, and 390px toolbar-trailer containment. Workspace navigation is covered in the same file, account-menu logout/session invalidation is covered by the core owner lifecycle and `auth.e2e.ts`, Settings behavior is covered under ADMIN-004, and publish affordances are exercised by publish/content specs.
6363

64-
ADMIN-004 note: `admin-navigation.e2e.ts` opens Settings from the Dashboard non-editor route, verifies General, Shortcuts, Publishing, and Preferences sections, writes Auto-save, Auto-save delay, and UI density through real controls, verifies reload persistence, verifies corrupt localStorage fallback, and checks 390px containment. DEF-20260623-ADMIN004-01 fixed a phone-width overflow where Preferences controls extended beyond the viewport; `SettingsModal.module.css` now switches to a single-column mobile shell with stacked preference rows.
64+
ADMIN-004 note: `admin-navigation.e2e.ts` opens Settings from the Dashboard non-editor route, verifies General, Shortcuts, Publishing, and Preferences sections, writes Auto-save, Auto-save delay, Theme, UI density, and UI text size through real controls, verifies reload persistence, verifies corrupt localStorage fallback, and checks 390px containment. DEF-20260623-ADMIN004-01 fixed a phone-width overflow where Preferences controls extended beyond the viewport; `SettingsModal.module.css` now switches to a single-column mobile shell with stacked preference rows.
6565

6666
ADMIN-005 note: focused Bun coverage spans workspace layout storage fallback/merge behavior, ToastProvider alert/status/dismiss behavior, ConfirmDeleteProvider alertdialog commit gating, no-native-dialog architecture enforcement, and error-boundary placement/root-callback gates. DEF-20260623-ADMIN005-01 fixed the Toast barrel so bus consumers can import `dismissToast` through the canonical `@ui/components/Toast` entrypoint. DEF-20260623-ADMIN005-02 fixed content left-panel mobile overflow after persisted desktop resizing. DEF-20260623-ADMIN005-03 fixed content right-settings mobile overflow when both sidebars are open after persisted desktop resizing. Dashboard, media, plugin, and admin-navigation E2E specs exercise route-level layout and toast surfaces; injected route-failure exploratory review remains future coverage.
6767

0 commit comments

Comments
 (0)