Theming

All visual properties in Davaux UI are expressed as CSS custom properties (--dv-*). Overriding the theme requires no JavaScript — just write CSS.

Primary color

The default primary color is blue. Override it by reassigning the --dv-color-primary-* tokens in your site's stylesheet, pointing them at any color scale in the palette.

/* layout.css — override primary to violet */
:root {
  --dv-color-primary-filled: var(--dv-color-violet-6);
  --dv-color-primary-filled-hover: var(--dv-color-violet-7);
  --dv-color-primary-filled-color: #fff;
  --dv-color-primary-light: var(--dv-color-violet-0);
  --dv-color-primary-light-hover: var(--dv-color-violet-1);
  --dv-color-primary-light-color: var(--dv-color-violet-7);
  --dv-color-primary-outline: var(--dv-color-violet-6);
  --dv-color-primary-outline-color: var(--dv-color-violet-6);
}

/* Dark mode adjustments */
[data-dv-color-scheme='dark'] {
  --dv-color-primary-filled: var(--dv-color-violet-7);
  --dv-color-primary-light: rgba(112, 72, 232, 0.15);
  --dv-color-primary-light-color: var(--dv-color-violet-4);
}

Color palette

The full palette is defined in @davaux/ui/styles.css and covers 17 scales × 10 shades each (-0 lightest through -9 darkest): dark, white, black, gray, red, crimson, pink, grape, violet, indigo, blue, cyan, teal, green, lime, yellow, and orange.

Raw palette tokens follow the pattern --dv-color-{name}-{0-9} (e.g. --dv-color-blue-6). 16 of the 17 scales also expose semantic variant tokens (-filled, -light, -outline) that automatically shift shades between light and dark mode.

See the Color Palette page for a full visual reference of every scale, semantic variant demo, and CSS variable naming guide.

Dark mode

Dark mode is controlled by the data-dv-color-scheme attribute on <html>. Set it in an inline script to avoid flash of unstyled content:

<script>
  (function () {
    var s = localStorage.getItem('dv-theme')
    var dark = s === 'dark' || (!s && matchMedia('(prefers-color-scheme: dark)').matches)
    document.documentElement.setAttribute('data-dv-color-scheme', dark ? 'dark' : 'light')
  })()
</script>

Toggle it from a client island:

// src/islands/ThemeToggle.tsx
import { createSignal, createEffect } from 'davaux/client'

export default function ThemeToggle() {
  const initial = document.documentElement.getAttribute('data-dv-color-scheme') ?? 'light'
  const [theme, setTheme] = createSignal<'dark' | 'light'>(initial as 'dark' | 'light')

  createEffect(() => {
    document.documentElement.setAttribute('data-dv-color-scheme', theme())
    localStorage.setItem('dv-theme', theme())
  })

  return (
    <button onClick={() => setTheme(theme() === 'dark' ? 'light' : 'dark')}>
      Toggle theme
    </button>
  )
}

Light/dark in inline styles

CSS custom properties on --dv-color-* handle dark mode automatically, but if you need a specific inline style value to differ between modes, use lightDark():

import { lightDark } from '@davaux/ui'

<Box style={{ border: `1px solid ${lightDark('#dee2e6', '#373a40')}` }}>
  Custom border
</Box>

lightDark(light, dark) emits the native CSS light-dark() function, which resolves based on the active color-scheme. Because Davaux UI sets color-scheme in sync with data-dv-color-scheme, the value tracks your theme toggle automatically — no JavaScript needed.

Semantic status tokens

Four semantic tokens map to the built-in color scales and respect dark mode automatically. Override them to change every error/success/warning/info indicator at once:

TokenDefault
--dv-color-error--dv-color-red-filled
--dv-color-success--dv-color-green-filled
--dv-color-warning--dv-color-yellow-filled
--dv-color-info--dv-color-blue-filled
:root {
  --dv-color-error: var(--dv-color-crimson-filled);
}

Components that use these tokens: form error messages, required-field asterisks.

Focus ring

All interactive components share a single focus ring token. Override it to restyle every keyboard focus indicator in one place:

:root {
  --dv-focus-ring: 0 0 0 3px rgba(112, 72, 232, 0.4);
}

The default value uses color-mix() to derive a semi-transparent tint from the primary color, so it adjusts automatically when you change --dv-color-primary-filled.

Typography tokens

TokenDefault
--dv-font-familySystem sans-serif stack
--dv-font-family-monospaceSystem monospace stack
--dv-font-family-headingsFalls back to --dv-font-family
--dv-font-size-xs--dv-font-size-xl0.75rem1.25rem
--dv-line-height-sm--dv-line-height-lg1.31.7

Override them at :root to apply a custom typeface across all components:

:root {
  --dv-font-family: 'Inter', sans-serif;
  --dv-font-family-headings: 'Cal Sans', sans-serif;
}

Spacing & radius

Components reference --dv-spacing-* and --dv-radius-* tokens:

TokenValue
--dv-spacing-xs0.5rem
--dv-spacing-sm0.75rem
--dv-spacing-md1rem
--dv-spacing-lg1.25rem
--dv-spacing-xl1.5rem
--dv-radius-xs2px
--dv-radius-sm4px
--dv-radius-md8px
--dv-radius-lg16px
--dv-radius-xl32px