Theming System

Matrix UI provides a powerful theming system based on CSS custom properties, enabling complete visual customization while maintaining consistency.

Built-in Themes

Matrix UI comes with 5 professionally designed themes:

Theme Structure

Each theme defines a set of design tokens using CSS custom properties:

interface Theme {
  name: string
  cssVars: {
    light: ThemeColors
    dark: ThemeColors
  }
  radius: string
}

interface ThemeColors {
  background: string
  foreground: string
  card: string
  cardForeground: string
  popover: string
  popoverForeground: string
  primary: string
  primaryForeground: string
  secondary: string
  secondaryForeground: string
  muted: string
  mutedForeground: string
  accent: string
  accentForeground: string
  destructive: string
  destructiveForeground: string
  border: string
  input: string
  ring: string
}

Design Tokens

Matrix UI uses a three-tier token system:

Raw Tokens

Base color values

--matrix-blue-500: #3b82f6
--matrix-gray-900: #111827
--matrix-red-600: #dc2626

Semantic Tokens

Contextual meanings

--primary: var(--matrix-blue-500)
--background: var(--matrix-white)
--destructive: var(--matrix-red-600)

Component Tokens

Component-specific values

--button-bg: var(--primary)
--button-hover: var(--primary-hover)
--card-border: var(--border)

Applying Themes

Using the Theme Utils

import { applyTheme, themes } from '@matrix-ui/themes'

// Apply a built-in theme
applyTheme(themes.carbon)

// Apply with specific mode
applyTheme(themes.obsidian, 'dark')

// Get stored theme preference
import { getStoredTheme } from '@matrix-ui/themes'
const savedTheme = getStoredTheme()
if (savedTheme) {
  applyTheme(savedTheme)
}

In a Next.js App

// app/layout.tsx
import { themes, applyTheme, getStoredTheme } from '@matrix-ui/themes'
import { useEffect } from 'react'

export default function RootLayout({ children }) {
  // Apply theme on mount
  useEffect(() => {
    const savedTheme = getStoredTheme()
    applyTheme(savedTheme || themes.carbon)
  }, [])

  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

Creating Custom Themes

You can create your own themes by defining the required tokens:

const myCustomTheme: Theme = {
  name: 'my-theme',
  cssVars: {
    light: {
      background: '0 0% 100%',
      foreground: '240 10% 3.9%',
      primary: '346.8 77.2% 49.8%',
      primaryForeground: '355.7 100% 97.3%',
      // ... other colors
    },
    dark: {
      background: '20 14.3% 4.1%',
      foreground: '0 0% 95%',
      primary: '346.8 77.2% 49.8%',
      primaryForeground: '355.7 100% 97.3%',
      // ... other colors
    }
  },
  radius: '0.5rem'
}

// Apply custom theme
applyTheme(myCustomTheme)

Theme Generator

Use the CLI to generate a theme from your brand colors:

npx @matrix-ui/cli theme generate --primary="#7c3aed" --name="purple"

Dark Mode

Matrix UI supports automatic dark mode switching:

CSS Class Strategy

// Toggle dark mode
document.documentElement.classList.toggle('dark')

// Check dark mode
const isDark = document.documentElement.classList.contains('dark')

System Preference

// Detect system preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches

// Listen for changes
window.matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => {
    if (e.matches) {
      document.documentElement.classList.add('dark')
    } else {
      document.documentElement.classList.remove('dark')
    }
  })

Theme Customization

Overriding Specific Tokens

/* In your global CSS */
:root {
  /* Override primary color */
  --primary: 262.1 83.3% 57.8%;
  
  /* Override radius */
  --radius: 0.75rem;
  
  /* Override specific component */
  --button-height: 2.75rem;
}

Component-Level Theming

// Using className for one-off customization
<Button 
  className="bg-purple-600 hover:bg-purple-700 text-white"
>
  Custom Styled Button
</Button>

// Creating variant with CVA
const customButtonVariants = cva(
  "inline-flex items-center justify-center",
  {
    variants: {
      variant: {
        brand: "bg-brand text-brand-foreground hover:bg-brand/90",
      }
    }
  }
)

Best Practices

Use Semantic Tokens

Always use semantic tokens (e.g., --primary) instead of raw colors to ensure your UI adapts to theme changes.

Maintain Contrast Ratios

Ensure your custom themes meet WCAG accessibility standards with proper contrast ratios between foreground and background colors.

Test Across Themes

Always test your components with multiple themes to ensure they look good in both light and dark modes.

Color Format

Matrix UI uses HSL color format for better manipulation and consistency:

HSL Format:
222.2 47.4% 11.2%
CSS Usage:
hsl(var(--primary))
With Opacity:
hsl(var(--primary) / 0.8)