Skip to content

Theme System

Vroum uses a Tailwind CSS v4 theme system built on CSS custom properties (OKLCH color space) with full dark mode support.

File Structure

resources/css/
├── app.css                  # Main entry — imports everything
├── themes/
│   ├── theme.css            # Base tokens (semantic aliases + custom palettes)
│   └── vroum.css            # Vroum brand overrides (imports theme.css)
  • theme.css declares all semantic color tokens and their default (blue-based) values.
  • vroum.css re-maps those tokens to the Vroum brand palette (cyan/teal, hue 180).
  • app.css imports vroum.css (which chains to theme.css) so the full system is loaded.

How It Works

  1. @theme inline in theme.css registers Tailwind utility names (e.g. bg-primary, text-foreground).
  2. Each utility references a CSS custom property (e.g. --color-primary → var(--primary)).
  3. :root sets light-mode values; .dark overrides them for dark mode.
  4. vroum.css uses [data-theme="theme-vroum"] to swap the brand palette in.

Using Theme Classes

Use the semantic token names directly as Tailwind utilities. Never hard-code color values — always use the theme tokens.

Backgrounds

Tailwind ClassLight ModePurpose
bg-background#ffffffPage background
bg-background-1~#f9fafbSlightly tinted background
bg-background-2~#f0f1f2Deeper tinted background
bg-plain#ffffffAlways-white surface
bg-layer#ffffffContainer / card-like surface
bg-surface~#f0f1f2Recessed surface
bg-muted~#f9fafbMuted/disabled background

Text

Tailwind ClassLight ModePurpose
text-foreground~#1f2937Default body text
text-foreground-inverse#ffffffText on dark surfaces
text-muted-foreground~#9ca3afPlaceholder / hint text
text-muted-foreground-1~#6b7280Secondary muted text
text-muted-foreground-2~#4b5563Stronger muted text

Primary (Brand)

The primary palette is the Vroum cyan/teal (hue 180). Use the shade scale or the state tokens.

Tailwind ClassVroum Hex (approx)OKLCHPurpose
bg-primary-50#c0f5eboklch(92.8% 0.08 180)Lightest tint
bg-primary-100#8deee0oklch(88.6% 0.1 180)Light tint
bg-primary-200#4fdecboklch(80.4% 0.12 180)Light accent
bg-primary-300#3dc6b1oklch(72.4% 0.14 180)Medium-light accent
bg-primary-400#1fae99oklch(64.6% 0.16 180)Medium accent
bg-primary-500#008a75oklch(57% 0.14 180)Base brand color
bg-primary-600#007462oklch(49.6% 0.12 180)Default primary
bg-primary-700#006050oklch(42.4% 0.1 180)Darker primary
bg-primary-800#004d3foklch(35.4% 0.08 180)Dark accent
bg-primary-900#003b30oklch(28.6% 0.06 180)Very dark
bg-primary-950#003028oklch(25.3% 0.05 180)Darkest

State tokens (use these for interactive elements):

Tailwind ClassResolves To (Light)Purpose
bg-primaryprimary-600Default button / accent
text-primary-foreground#ffffffText on primary background
bg-primary-hoverprimary-700Hover state
bg-primary-focusprimary-700Focus state
bg-primary-activeprimary-700Active / pressed state
bg-primary-checkedprimary-600Checked checkbox / toggle
border-primary-linetransparentPrimary border (if needed)

Secondary

Tailwind ClassLight ModePurpose
bg-secondary~#1a202eDark button / accent
text-secondary-foreground#ffffffText on secondary bg
bg-secondary-hover~#2d3748Hover state

Destructive

Tailwind ClassLight ModePurpose
bg-destructive~#ef4444Danger / delete
text-destructive-foreground#ffffffText on destructive
bg-destructive-hover~#dc2626Hover state

Borders

Tailwind ClassLight ModePurpose
border-border~#e5e7ebDefault border
border-line-1~#f3f4f6Subtle separator
border-line-2~#e5e7ebStandard separator
border-line-3~#d1d5dbProminent border
border-line-4~#9ca3afStrong border
…through line-8~#1f2937Strongest border

Component Tokens

Each UI component has its own set of tokens. They all follow the same pattern:

bg-{component}             → background
border-{component}-line    → border color
text-{component}-foreground (if applicable)
bg-{component}-hover       → hover state
bg-{component}-divider     → internal divider
bg-{component}-inverse     → inverted accent

Available component groups:

ComponentClass PrefixExample
Navbarnavbar-bg-navbar, bg-navbar-nav-hover
Navbar 1navbar-1-bg-navbar-1, border-navbar-1-line
Navbar 2navbar-2-bg-navbar-2, bg-navbar-2-nav-active
Sidebarsidebar-bg-sidebar, bg-sidebar-nav-active
Sidebar 1sidebar-1-bg-sidebar-1, border-sidebar-1-line
Sidebar 2sidebar-2-bg-sidebar-2
Cardcard-bg-card, border-card-line
Dropdowndropdown-bg-dropdown, bg-dropdown-item-hover
Selectselect-bg-select, bg-select-item-hover
Overlayoverlay-bg-overlay, border-overlay-line
Popoverpopover-bg-popover, border-popover-line
Tooltiptooltip-bg-tooltip, text-tooltip-foreground
Footerfooter-bg-footer, border-footer-line
Tabletable-border-table-line
Scrollbarscrollbar-bg-scrollbar-track, bg-scrollbar-thumb

Surface Depth Scale

For layered UIs, the surface scale provides increasing depth:

Tailwind ClassLight ModeDark ModePurpose
bg-surfacegray-100zinc-700Level 0 (base)
bg-surface-1gray-200zinc-600Level 1
bg-surface-2gray-300zinc-500Level 2
bg-surface-3gray-400zinc-600Level 3
bg-surface-4gray-500zinc-500Level 4
bg-surface-5gray-600zinc-400Level 5 (deepest)

Charts

Chart tokens provide hex values for libraries like ApexCharts that don't support OKLCH:

Token (CSS var)Hex Value
--chart-colors-primary-hex#008a75
--chart-colors-chart-1-hex#008a75
--chart-colors-chart-2-hex#0092a8
--chart-colors-chart-3-hex#3d8e53
--chart-colors-chart-4-hex#ac4c6e
--chart-colors-chart-5-hex#a5679f
--chart-colors-chart-6-hex#b25f52
--chart-colors-chart-7-hex#478ebc
--chart-colors-chart-8-hex#6d7d34
--chart-colors-chart-9-hex#6b7db6
--chart-colors-chart-10-hex#8f7835

Access them in JS via getComputedStyle(document.documentElement).getPropertyValue('--chart-colors-primary-hex').

Custom Palettes

Beyond the semantic tokens, these raw color palettes are available as Tailwind utilities:

Vroum Brand (vroum-*)

Vibrant cyan/teal at hue 180. Available shades: 50–950.

html
<div class="bg-vroum-500 text-white">Brand element</div>

Vroum Gray (vroum-gray-*)

Teal-tinted neutral gray. Available shades: 50–950.

html
<div class="bg-vroum-gray-100 text-vroum-gray-800">Tinted surface</div>

Other Palettes

PaletteHueUsage
khaki-*67–91Earthy/warm accents
mauve-*334–345Soft pink accents
avocado-*120Green accents (vibrant)
avocado-soft-*120Green accents (muted)

Dark Mode

Dark mode activates when the .dark class is present on <html>. Toggle it via resources/js/Plugins/switchDark.ts:

ts
import { toggle, isDark, enable, disable } from '@/Plugins/switchDark';

toggle();       // flip current state
isDark();       // returns true/false
enable();       // force dark
disable();      // force light

The theme automatically adjusts all semantic tokens — no extra classes needed. The Vroum dark mode uses Tailwind's zinc palette for neutral surfaces.

If you need mode-specific overrides in templates, use the dark: variant:

html
<div class="bg-layer dark:bg-zinc-900">
    <!-- Usually not needed — the token handles it -->
</div>

Examples

Primary Button

html
<button class="bg-primary text-primary-foreground hover:bg-primary-hover focus:bg-primary-focus rounded-lg px-4 py-2">
    Save
</button>

Card

html
<div class="bg-card border border-card-line rounded-xl p-6">
    <h3 class="text-foreground font-semibold">Title</h3>
    <p class="text-muted-foreground">Description text</p>
    <hr class="border-card-divider my-4" />
    <footer class="text-muted-foreground-1 text-sm">Footer</footer>
</div>
html
<a class="text-sidebar-nav-foreground hover:bg-sidebar-nav-hover focus:bg-sidebar-nav-focus px-3 py-2 rounded-md">
    Dashboard
</a>

Destructive Action

html
<button class="bg-destructive text-destructive-foreground hover:bg-destructive-hover rounded-lg px-4 py-2">
    Delete
</button>

Muted Badge

html
<span class="bg-muted text-muted-foreground-1 rounded-full px-2 py-0.5 text-xs">
    Draft
</span>

Rules

  1. Always use semantic tokens (bg-primary, text-foreground, border-line-2) instead of raw Tailwind colors (bg-blue-600, text-gray-800).
  2. Don't hard-code hex values in templates — the theme system handles light/dark mode automatically.
  3. Use component tokens for their intended components (bg-card for cards, bg-dropdown for dropdowns) to ensure consistency.
  4. Use the -hex chart tokens when passing colors to JS charting libraries that require hex strings.
  5. Run bg-primary-* for the brand color scale, not bg-vroum-*, unless you need the raw palette outside of theming.