5.1 — Theme System
Previous Step: ← Templates
Next Step: → Mobile Experience
Page Metadata
| Property |
Value |
| Scenario |
05 — Theming |
| Page Number |
5.1 |
| Platform |
Web (PWA), portable to macOS/Windows |
| Page Type |
Dropdown Panel + Settings Section |
Overview
Page Purpose: Enable users to personalize their workspace with preset themes and custom accent colors. Theming is a personality differentiator — especially the Matrix theme, which gives CalcText a unique identity in the calculator app market.
Success Criteria:
- Theme switches instantly (< 16ms, no flash of unstyled content)
- Matrix theme makes users want to screenshot and share
- Custom accent color gives ownership feeling
- Theme persists across sessions
Theme Architecture
All theming works through CSS custom properties on :root. Switching themes = swapping property values. No component changes, no re-renders beyond what CSS handles natively.
Preset Themes
Light
| Token |
Value |
| --bg |
#ffffff |
| --bg-secondary |
#f8f9fa |
| --text |
#6b6375 |
| --text-h |
#08060d |
| --border |
#e5e4e7 |
| --accent |
#6366f1 |
| --stripe |
rgba(0, 0, 0, 0.02) |
| Feel |
Clean, airy, professional |
Dark
| Token |
Value |
| --bg |
#16171d |
| --bg-secondary |
#1a1b23 |
| --text |
#9ca3af |
| --text-h |
#f3f4f6 |
| --border |
#2e303a |
| --accent |
#818cf8 |
| --stripe |
rgba(255, 255, 255, 0.025) |
| Feel |
Calm, focused, modern |
Matrix
| Token |
Value |
| --bg |
#0a0a0a |
| --bg-secondary |
#0f1a0f |
| --text |
#00ff41 |
| --text-h |
#33ff66 |
| --border |
#003300 |
| --accent |
#00ff41 |
| --stripe |
rgba(0, 255, 65, 0.03) |
| --syntax-* |
Green spectrum (#00cc33 to #39ff14) |
| --result-currency |
#ffff00 (yellow — stands out in green) |
| fontOverride |
'Courier New', 'Fira Code', monospace |
| specialEffect |
matrix-scanlines |
| Feel |
Iconic, hackery, fun |
Matrix Special Effects
Scanlines (optional, subtle):
Cursor glow:
Text glow (subtle):
Midnight
| Token |
Value |
| --bg |
#0f172a |
| --bg-secondary |
#1e293b |
| --text |
#94a3b8 |
| --text-h |
#e2e8f0 |
| --border |
#334155 |
| --accent |
#38bdf8 (sky-400) |
| --stripe |
rgba(56, 189, 248, 0.03) |
| Feel |
Deep blue, serene, late-night coding |
Warm
| Token |
Value |
| --bg |
#fffbf5 |
| --bg-secondary |
#fef3e2 |
| --text |
#78716c |
| --text-h |
#1c1917 |
| --border |
#e7e5e4 |
| --accent |
#f97316 (orange-500) |
| --stripe |
rgba(249, 115, 22, 0.03) |
| Feel |
Paper-like, warm, comfortable for long sessions |
Theme Picker Dropdown
OBJECT ID: theme-picker
| Property |
Value |
| Trigger |
Click theme icon in header or status bar, or Ctrl+Shift+T |
| Position |
Dropdown below header button, right-aligned |
| Width |
240px |
| Background |
var(--bg) |
| Border |
1px solid var(--border) |
| Border radius |
8px |
| Shadow |
0 4px 16px rgba(0, 0, 0, 0.15) |
| Padding |
space-xs (6px) |
| Animation |
Scale from 95% + fade, 150ms ease-out |
| Dismiss |
Click outside, Esc, or select theme |
Theme Picker Layout
Theme Item
| Property |
Value |
| Height |
36px |
| Padding |
8px 12px |
| Layout |
Icon + name + optional checkmark |
| Hover |
var(--accent-bg) background, border-radius 4px |
| Active |
Checkmark ✓ on right side, weight 500 |
| Click |
Apply theme instantly, close picker |
| Preview |
On hover, show a 4-color mini-swatch (bg, text, accent, secondary) |
Color Swatch Preview (on hover)
| Property |
Value |
| Size |
4 circles, 12px each, 4px gap |
| Colors |
bg, bg-secondary, accent, text — of the hovered theme |
| Position |
Inline after theme name |
Accent Color Picker
OBJECT ID: theme-accent-picker
| Property |
Value |
| Location |
Inside theme picker dropdown, below themes |
| Presets |
7 color swatches in a row |
| Swatch size |
20px circles, 6px gap |
| Active swatch |
2px ring in var(--text-h) |
| Custom |
Last swatch is rainbow gradient → opens native color picker |
| Behavior |
Overrides --accent, --accent-bg, --accent-border for current theme |
| Persistence |
Stored as accentColor in localStorage |
Preset Accent Colors
| Name |
Value |
Hex |
| Indigo (default) |
Indigo 500/400 |
#6366f1 / #818cf8 |
| Teal |
Teal 500/400 |
#14b8a6 / #2dd4bf |
| Rose |
Rose 500/400 |
#f43f5e / #fb7185 |
| Amber |
Amber 500/400 |
#f59e0b / #fbbf24 |
| Emerald |
Emerald 500/400 |
#10b981 / #34d399 |
| Sky |
Sky 500/400 |
#0ea5e9 / #38bdf8 |
| Custom |
User pick |
Via <input type="color"> |
Each preset has light/dark variants. The correct variant is selected based on current base theme.
System Theme Option
OBJECT ID: theme-system
| Property |
Value |
| Behavior |
Follows OS prefers-color-scheme |
| Matches |
Light ↔ Light theme, Dark ↔ Dark theme |
| Override |
Selecting any specific theme disables system following |
| Re-enable |
Select "System (auto)" in picker |
| Label |
"⚙️ System (auto)" with current resolved theme name |
Theme Application Flow
CodeMirror Theme Sync
| Step |
Action |
| 1 |
Theme changes → dispatch new baseTheme to EditorView |
| 2 |
Syntax highlighting colors update via CSS variables (no extension swap) |
| 3 |
Stripe colors update via CSS |
| 4 |
Active line highlight updates via CSS |
| 5 |
Only the base theme extension needs reconfiguration |
Responsive
| Breakpoint |
Theme Picker |
| >= 768px |
Dropdown panel below header button |
| < 768px |
Bottom sheet (slides up from bottom, 60vh max height) |
Mobile Bottom Sheet
| Property |
Value |
| Width |
100vw |
| Max height |
60vh |
| Border radius |
12px 12px 0 0 (top corners) |
| Drag handle |
32px × 4px pill, centered |
| Backdrop |
50% black overlay |
| Animation |
Slide up 200ms ease-out |
| Close |
Swipe down, tap backdrop |
Page States
| State |
When |
Behavior |
| First launch |
No theme preference |
Follow OS (system). If OS is dark, use Dark. |
| Theme selected |
User picked a theme |
Applied instantly, persisted. System mode disabled. |
| System mode |
User selected "System (auto)" |
Listens to OS changes in real-time. |
| Custom accent |
User picked accent color |
Overrides accent tokens. Works with any base theme. |
| Matrix active |
Matrix theme selected |
Font override applied. Scanline effect enabled. Green cursor glow. |
Technical Notes
- No Flash of Unstyled Content (FOUC): Load theme from localStorage in
<script> in <head> BEFORE React mounts. Set data-theme on <html> synchronously.
- CSS structure: Each theme is a
[data-theme="name"] selector block overriding :root variables.
- Matrix performance: Scanline effect uses
pointer-events: none and is pure CSS. No performance impact.
- Cross-platform: macOS/Windows use native appearance APIs. Theme names map to native equivalents. Matrix theme = custom dark palette on all platforms.
- PWA: Update
<meta name="theme-color"> dynamically when theme changes for native status bar color.
Created using Whiteport Design Studio (WDS) methodology