Theme Customization
Whity Core uses a comprehensive CSS custom properties (variables) system for theming, powered by OKLCH color space for perceptually uniform colors across light and dark modes.
Token Architecture
Section titled “Token Architecture”src/design/tokens/├── base.json ← Master definitions├── generate-tokens.js ← Generation script└── generated/ ├── tokens.json ← For programmatic use └── tokens.dart ← For Flutter mobile
web/app/└── globals.css ← Web tokens (source of truth)Token Structure
Section titled “Token Structure”Core UI Colors
Section titled “Core UI Colors”| Token | Purpose |
|---|---|
background / foreground |
Page backgrounds and text |
card / card-foreground |
Card component surfaces |
popover / popover-foreground |
Dropdown/tooltip surfaces |
primary / primary-foreground |
Primary actions and buttons |
secondary / secondary-foreground |
Secondary interactive elements |
muted / muted-foreground |
Disabled/inactive states |
accent / accent-foreground |
Emphasis and highlights |
destructive |
Dangerous actions (delete, confirm) |
UI Element Tokens
Section titled “UI Element Tokens”border— Component bordersinput— Input field backgrounds and bordersring— Focus ring color for keyboard navigation
Data Visualization
Section titled “Data Visualization”chart-1throughchart-5— Chart and graph colors for consistency
Navigation (Sidebar)
Section titled “Navigation (Sidebar)”sidebar,sidebar-foreground— Navigation background and textsidebar-primary,sidebar-primary-foreground— Active sidebar itemssidebar-accent,sidebar-accent-foreground— Sidebar emphasissidebar-border,sidebar-ring— Sidebar borders and focus
Spacing
Section titled “Spacing”radius— Base border radius value (10px = 0.625rem)- Derived values:
radius-sm,radius-md,radius-lg,radius-xl,radius-2xl,radius-3xl,radius-4xl
Color Spaces
Section titled “Color Spaces”OKLCH is used for all colors because it’s perceptually uniform:
- L (Lightness) — 0 (dark) to 1 (light) — roughly perception
- C (Chroma) — Color saturation intensity
- H (Hue) — Color angle (0-360°)
Example: oklch(0.578 0.245 27.325) = A red-orange color
Light and Dark Modes
Section titled “Light and Dark Modes”Light Mode (:root)
Section titled “Light Mode (:root)”Default colors with high lightness for white backgrounds and dark text.
Dark Mode (.dark)
Section titled “Dark Mode (.dark)”Inverted with dark backgrounds and light text, with adjusted OKLCH values for readability.
Customizing Your Theme
Section titled “Customizing Your Theme”Quick Start with Token Generator
Section titled “Quick Start with Token Generator”The fastest way to create custom tokens:
- Visit: https://ui.shadcn.com/create
- Choose your brand color in the color picker
- Preview light and dark modes
- Copy the generated CSS
- Paste into
web/app/globals.css
Manual Customization
Section titled “Manual Customization”Edit web/app/globals.css:
:root { --primary: oklch(0.205 0 0); /* Change primary color */ --accent: oklch(0.97 0 0); /* Change accent */ --destructive: oklch(0.577 0.245 27.325); /* Change destructive */ --radius: 0.625rem; /* Change border radius */}
.dark { --primary: oklch(0.922 0 0); /* Dark mode primary */ --background: oklch(0.145 0 0); /* Dark background */ /* ... rest of dark tokens ... */}Using Tokens in Components
Section titled “Using Tokens in Components”With Tailwind CSS, tokens are automatically available as classes:
// Using color tokens<button className="bg-primary text-primary-foreground"> Save Changes</button>
// Using semantic tokens<div className="bg-card text-card-foreground border border-border"> Card Content</div>
// Using state tokens<input className="border border-input focus:ring-2 focus:ring-ring" />
// Using radius tokens<div className="rounded-lg">Rounded corner</div>White-Label Customization
Section titled “White-Label Customization”For multi-tenant applications, tokens can be customized per tenant by generating CSS variables server-side:
Approach
Section titled “Approach”- Store tenant preferences in database
- Generate CSS from preferences on server
- Inject into page as
<style>tag in HTML head
Example Flow
Section titled “Example Flow”// In layout.tsxexport default function RootLayout({ children, tenant }) { // Generate CSS variables from tenant config const tenantCss = generateCssForTenant(tenant);
// Inject as style tag (safe because generated server-side) return ( <html> <head> <style>{tenantCss}</style> </head> <body>{children}</body> </html> );}
// Helper functionfunction generateCssForTenant(tenant) { const { primary, accent, radius } = tenant.theme; return ` :root { --primary: ${primary}; --accent: ${accent}; --radius: ${radius}; } `;}The CSS cascade ensures all components automatically use tenant-specific tokens.
Font Customization
Section titled “Font Customization”Fonts are defined in web/app/layout.tsx and configured in Tailwind:
@theme inline { --font-sans: var(--font-sans); /* Body text, UI */ --font-mono: var(--font-geist-mono); /* Code blocks */ --font-heading: var(--font-sans); /* Headings */}To change fonts:
- Install font package:
npm install next/font - Import in
app/layout.tsx - Update
--font-*variables - Update tailwind config
Accessibility
Section titled “Accessibility”All color tokens are designed for WCAG AA+ contrast:
- Foreground colors on background colors maintain 7:1+ contrast
- Focus states (
ringcolor) clearly visible on all backgrounds - High Contrast theme variant available for accessibility needs
Token Generation
Section titled “Token Generation”Tokens are automatically generated for multiple platforms:
Generate All Tokens
Section titled “Generate All Tokens”cd webnpm run tokens:generateGenerate Specific Formats
Section titled “Generate Specific Formats”# JSON for programmatic accessnpm run tokens:generate:json
# Dart for Flutter mobilenpm run tokens:generate:dartGenerated Output
Section titled “Generated Output”tokens.json — For programmatic use:
{ "light": { "primary": "oklch(...)", ... }, "dark": { "primary": "oklch(...)", ... }, "fonts": { "font-sans": "...", ... }}tokens.dart — For Flutter:
class AppTokens { static const lightTokens = <String, Color>{ 'primary': Color(0xFF3B82F6), // ... }; static const darkTokens = <String, Color>{...};}For White-Label Tenants
Section titled “For White-Label Tenants”- Load
tokens.jsonprogrammatically - Customize colors per tenant
- Generate CSS variables dynamically
- Inject at runtime
const baseTokens = require('./tokens.json');const tenantTokens = { ...baseTokens, ...customization };const css = generateCss(tenantTokens);// Inject into pageResources
Section titled “Resources”- shadcn Token Generator: https://ui.shadcn.com/create
- OKLCH Colors: https://oklch.com/ (interactive color picker)
- Color Contrast Checker: https://www.tpgi.com/color-contrast-checker/
- Tailwind CSS Variables: https://tailwindcss.com/docs/adding-custom-styles#using-css-variables
- Token Generation: See
src/design/tokens/generate-tokens.jsin repository