Theming
VelocityUI uses CSS custom properties scoped to theme classes. Switching themes requires adding a single class — no JavaScript, no re-renders.
How it works
Each theme defines a set of CSS custom properties (e.g. --vui-primary, --vui-surface) under a selector like .vui-theme-midnight. Every VelocityUI component reads these variables, so they automatically adapt when the class is present on any ancestor element.
<!-- Apply to the entire page -->
<body class="vui-theme-midnight">
<!-- Or scope to a specific section -->
<div class="vui-theme-ocean">
<!-- Only components inside here use the ocean theme -->
</div>Available themes
| Class | Description |
|---|---|
vui-theme-default | Clean neutral palette suitable for most products. |
vui-theme-midnight | Deep dark backgrounds with vibrant accent colors. |
vui-theme-ocean | Cool blues and teals for a calm, professional look. |
vui-theme-dark-cyan | Neutral carbon dark base with vivid cyan accents. |
vui-theme-tangerine | Sunlit orange accents with warm, citrus-inspired surfaces. |
vui-theme-construction | High-visibility yellows and blacks. |
vui-theme-glass | Frosted glass surfaces with subtle blur effects. |
vui-theme-soft | Muted pastels for a gentle, approachable feel. |
vui-theme-high-contrast | Maximum contrast ratios for accessibility compliance. |
vui-theme-monochrome-red | Bold red accents on a monochrome base. |
/* All available theme classes */
vui-theme-default
vui-theme-midnight
vui-theme-ocean
vui-theme-dark-cyan
vui-theme-tangerine
vui-theme-construction
vui-theme-glass
vui-theme-soft
vui-theme-high-contrast
vui-theme-monochrome-redDensity modifiers
Density modifiers control the padding and spacing of all components in a region. Combine them with any theme class.
| Class | Description |
|---|---|
vui-density-compact | Reduced padding and tighter spacing — ideal for data-dense UIs like dashboards. |
vui-density-comfortable | The default density. Balanced spacing for general-purpose apps. |
vui-density-spacious | Generous padding and breathing room — ideal for marketing and landing pages. |
<!-- Theme + density combined -->
<body class="vui-theme-midnight vui-density-compact">
<body class="vui-theme-ocean vui-density-spacious">
<!-- Mix density in a subsection -->
<body class="vui-theme-default">
<header class="vui-density-compact">...</header>
<main class="vui-density-comfortable">...</main>
</body>Dynamic theming in React
Because theming is CSS-class-based, switching themes at runtime is as simple as updating a class string. No React context or re-render of component subtrees is required.
import { useState } from 'react'
const themes = ['default', 'midnight', 'ocean', 'tangerine', 'construction', 'glass', 'soft'] as const
type Theme = (typeof themes)[number]
export function ThemeSwitcher() {
const [theme, setTheme] = useState<Theme>('default')
return (
<div className={`vui-theme-${theme}`}>
<select
value={theme}
onChange={(e) => setTheme(e.target.value as Theme)}
>
{themes.map((t) => (
<option key={t} value={t}>{t}</option>
))}
</select>
{/* Components here react to theme instantly */}
</div>
)
}Custom CSS variables
You can override any CSS custom property to create your own palette. Override at the :root level or scope to a class.
/* globals.css — override the default theme */
:root {
--vui-primary: #7c3aed;
--vui-primary-soft: #ede9fe;
--vui-surface: #ffffff;
--vui-surface-muted: #f5f3ff;
--vui-text: #1e1b4b;
--vui-text-muted: #4c1d95;
--vui-text-subtle: #6d28d9;
--vui-border: #ddd6fe;
}
/* Or scope overrides to a custom class */
.my-brand-theme {
--vui-primary: #dc2626;
--vui-primary-soft: #fee2e2;
}Token reference
| Variable | Usage |
|---|---|
--vui-primary | Primary action color for buttons, links, focus rings |
--vui-primary-soft | Light tint of primary used for active backgrounds |
--vui-surface | Default surface/card background color |
--vui-surface-muted | Subtle background for inputs, code blocks, hover states |
--vui-text | Primary body text color |
--vui-text-muted | Secondary text, labels, placeholders |
--vui-text-subtle | Tertiary text, hints, captions |
--vui-border | Default border color for inputs, cards, dividers |