VelocityUI logoVelocityUI

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.

html
<!-- 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

ClassDescription
vui-theme-defaultClean neutral palette suitable for most products.
vui-theme-midnightDeep dark backgrounds with vibrant accent colors.
vui-theme-oceanCool blues and teals for a calm, professional look.
vui-theme-dark-cyanNeutral carbon dark base with vivid cyan accents.
vui-theme-tangerineSunlit orange accents with warm, citrus-inspired surfaces.
vui-theme-constructionHigh-visibility yellows and blacks.
vui-theme-glassFrosted glass surfaces with subtle blur effects.
vui-theme-softMuted pastels for a gentle, approachable feel.
vui-theme-high-contrastMaximum contrast ratios for accessibility compliance.
vui-theme-monochrome-redBold red accents on a monochrome base.
css
/* 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-red

Density modifiers

Density modifiers control the padding and spacing of all components in a region. Combine them with any theme class.

ClassDescription
vui-density-compactReduced padding and tighter spacing — ideal for data-dense UIs like dashboards.
vui-density-comfortableThe default density. Balanced spacing for general-purpose apps.
vui-density-spaciousGenerous padding and breathing room — ideal for marketing and landing pages.
html
<!-- 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.

tsx
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.

css
/* 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

VariableUsage
--vui-primaryPrimary action color for buttons, links, focus rings
--vui-primary-softLight tint of primary used for active backgrounds
--vui-surfaceDefault surface/card background color
--vui-surface-mutedSubtle background for inputs, code blocks, hover states
--vui-textPrimary body text color
--vui-text-mutedSecondary text, labels, placeholders
--vui-text-subtleTertiary text, hints, captions
--vui-borderDefault border color for inputs, cards, dividers

Next steps