Customization

Theming & Dark Mode

Overview

Vextro uses a two-tier token system defined in vextro.css. All semantic tokens use the --vx-* prefix and store space-separated RGB values for opacity support. Tailwind utility classes are mapped from these tokens via the @theme inline block.

TierPurposeExample
PrimitivesBase zinc-based neutral scale--neutral-500: 113 113 122
Semantic--vx-* prefixed UI colors--vx-primary-rgb: 37 99 235

Semantic tokens map directly to Tailwind utilities: --vx-fg powers text-fg, --vx-surface powers bg-surface, --vx-edge powers border-edge.

Token Reference

Foreground (Text Hierarchy)

TokenTailwind ClassLightDark
--vx-fgtext-fgneutral-900neutral-100
--vx-fg-secondarytext-fg-secondaryneutral-600neutral-300
--vx-fg-mutedtext-fg-mutedneutral-500neutral-400
--vx-fg-fainttext-fg-faintneutral-400neutral-500
--vx-fg-inversetext-fg-inversewhiteneutral-900

Surface (Background Hierarchy)

TokenTailwind ClassLightDark
--vx-surfacebg-surfacewhiteneutral-900
--vx-surface-subtlebg-surface-subtleneutral-50neutral-800
--vx-surface-mutedbg-surface-mutedneutral-100neutral-700
--vx-surface-emphasisbg-surface-emphasisneutral-200neutral-600
--vx-surface-inversebg-surface-inverseneutral-900neutral-100

Edge (Border Hierarchy)

TokenTailwind ClassLightDark
--vx-edgeborder-edgeneutral-200neutral-700
--vx-edge-mutedborder-edge-mutedneutral-100neutral-750
--vx-edge-emphasisborder-edge-emphasisneutral-300neutral-600

Status Colors

Each status color has base, hover, subtle, and muted variants.

TokenTailwind ClassDescription
--vx-primary-rgbtext-primaryBrand accent (blue)
--vx-successtext-successPositive actions (green)
--vx-warningtext-warningCaution states (amber)
--vx-dangertext-dangerErrors, destructive (red)
--vx-infotext-infoInformational (cyan)

Variants follow the pattern --vx-{status}-hover, --vx-{status}-subtle, --vx-{status}-muted. Tailwind classes follow: bg-success-subtle, text-danger-hover, border-warning-muted, etc.

Customizing the Theme

Override tokens in your app CSS after importing Vextro styles. Only override the tier you need.

@import "vextro/styles.css";

:root {
  --vx-primary-rgb: 124 58 237;        /* violet accent */
  --vx-primary-hover: 109 40 217;
  --vx-primary-subtle: 245 243 255;
}

.dark, [data-theme="dark"] {
  --vx-primary-rgb: 139 92 246;
  --vx-primary-hover: 167 139 250;
  --vx-primary-subtle: 46 16 101;
}

All tokens use space-separated RGB values (e.g. 124 58 237) so they work with opacity modifiers: rgb(var(--vx-primary-rgb) / 0.5).

Dark Mode

Dark mode activates via the .dark class or [data-theme="dark"] attribute. Vextro overrides every semantic token inside this selector. Theme transitions use a smooth 200ms duration, respecting prefers-reduced-motion.

The token names stay the same between modes -- only the values change. This means components automatically adapt without any mode-specific logic.

Tailwind Integration

The @theme inline block maps --vx-* tokens to Tailwind utilities:

@theme inline {
  --color-fg: rgb(var(--vx-fg));
  --color-surface: rgb(var(--vx-surface));
  --color-edge: rgb(var(--vx-edge));
  --color-primary: rgb(var(--vx-primary-rgb));
  /* ... */
}

This generates Tailwind classes like text-fg, bg-surface, border-edge, text-primary. Use these classes in templates instead of referencing CSS variables directly.

In scoped <style> blocks where Tailwind classes are not available, use rgb(var(--vx-*)):

.my-element {
  color: rgb(var(--vx-fg));
  background: rgb(var(--vx-surface-muted));
  border-color: rgb(var(--vx-edge));
}

Best Practices

  • To ensure dark mode compatibility, reference --vx-* tokens instead of hardcoded hex colors in component styles.
  • Avoid CSS variable fallbacks with light-mode defaults (e.g. var(--color, #f3f4f6)) — add missing tokens to the token system instead.
  • Prefer semantic Tailwind classes (text-fg, bg-surface, border-edge) over fixed Tailwind colors for automatic theme adaptation.
  • In scoped <style> blocks, use the rgb(var(--vx-*)) format to reference tokens.
  • SVG data URIs with embedded colors should include a .dark override for the alternate palette.
  • Components should be verified in both light and dark mode to ensure full theme compatibility.
Previous
Preview Listener