Overview
Stride Design System uses a powerful CSS variable-based theming architecture that separates foundation tokens (spacing, radius, shadows) from semantic tokens (colors, interactive states). This separation enables:
Consistent design language across brands
Automatic dark/light mode support
Easy customization without touching component code
Runtime theme switching
Token Architecture
Foundation Tokens
Foundation tokens define the base design language and are brand-agnostic. These are defined in styles.css:
Spacing Scale
Border Radius
Shadows
:root {
--spacing-xs : 0.25 rem ; /* 4px */
--spacing-sm : 0.5 rem ; /* 8px */
--spacing-md : 0.75 rem ; /* 12px */
--spacing-lg : 1 rem ; /* 16px */
--spacing-xl : 1.5 rem ; /* 24px */
--spacing-2xl : 2 rem ; /* 32px */
--spacing-3xl : 3 rem ; /* 48px */
--spacing-4xl : 4 rem ; /* 64px */
--spacing-5xl : 6 rem ; /* 96px */
}
Semantic Tokens
Semantic tokens map to specific UI purposes and adapt per brand. Defined in brands.css:
Text Tokens
Background Tokens
Interactive Tokens
Border & Status Tokens
.brand-stride {
--text-primary : var ( --brand-neutral-900 ); /* Main text */
--text-secondary : var ( --brand-neutral-600 ); /* Subtitles */
--text-tertiary : var ( --brand-neutral-500 ); /* Captions */
--text-inverse : var ( --brand-neutral-0 ); /* On dark bg */
--text-disabled : var ( --brand-neutral-400 ); /* Disabled */
--text-link : var ( --brand-primary-600 ); /* Links */
--text-link-hover : var ( --brand-primary-700 ); /* Link hover */
}
Component Tokens
Component-specific tokens for consistent sizing and spacing:
:root {
/* Button sizing */
--button-height-sm : 2 rem ; /* 32px */
--button-height-md : 2.5 rem ; /* 40px */
--button-height-lg : 3 rem ; /* 48px */
--button-padding-sm : 0 0.75 rem ;
--button-padding-md : 0 1 rem ;
--button-padding-lg : 0 1.5 rem ;
--radius-button : var ( --radius-full ); /* Pill-shaped by default */
/* Input sizing */
--input-height-sm : 2.25 rem ; /* 36px */
--input-height-md : 2.75 rem ; /* 44px */
--input-height-lg : 3.25 rem ; /* 52px */
/* Card tokens */
--card-padding-sm : 1 rem ;
--card-padding-md : 1.5 rem ;
--card-padding-lg : 2 rem ;
--card-radius : var ( --radius-3xl ); /* 24px */
}
Dark Mode Support
Each brand has automatic dark mode variants that adapt semantic tokens:
Light Mode (Default)
Dark Mode Override
.brand-stride {
--text-primary : var ( --brand-neutral-900 ); /* Dark text */
--bg-primary : var ( --brand-neutral-0 ); /* White bg */
--border-primary : var ( --brand-neutral-200 ); /* Light border */
}
Toggling Dark Mode
Manual Toggle
System Preference Detection
With State Persistence
// Toggle dark mode
function toggleDarkMode () {
const html = document . documentElement ;
html . classList . toggle ( 'dark' );
}
Using Tokens in Components
Components reference semantic tokens using CSS custom properties:
Button Component
Card Component
import { cva } from 'class-variance-authority' ;
import { cn } from '@/lib/utils' ;
const buttonVariants = cva (
[
'inline-flex items-center justify-center' ,
'[border-radius:var(--radius-button)]' ,
'[transition-duration:var(--transition-normal)]' ,
],
{
variants: {
variant: {
primary: [
'[background-color:var(--interactive-primary)]' ,
'[color:var(--interactive-primary-text)]' ,
'hover:[background-color:var(--interactive-primary-hover)]' ,
],
secondary: [
'[background-color:var(--interactive-secondary)]' ,
'[color:var(--text-primary)]' ,
],
},
size: {
sm: '[height:var(--button-height-sm)]' ,
md: '[height:var(--button-height-md)]' ,
lg: '[height:var(--button-height-lg)]' ,
},
},
}
);
Tailwind CSS v4 Integration
Stride uses Tailwind v4 with inline theme configuration that maps to semantic tokens:
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-family-primary);
/* Brand-aware color mapping */
--color-primary: var(--interactive-primary);
--color-success: var(--status-success);
--color-warning: var(--status-warning);
--color-danger: var(--status-danger);
/* Semantic neutral scale */
--color-neutral-0: var(--bg-primary);
--color-neutral-100: var(--bg-tertiary);
--color-neutral-800: var(--text-primary);
}
This allows you to use Tailwind utilities like bg-primary or text-neutral-800 that automatically adapt to the active brand and theme.
Best Practices
Always use semantic tokens in components
Instead of hardcoding colors or using brand tokens directly, use semantic tokens: // ❌ Bad - hardcoded color
< div className = "bg-[#0ea5e9]" />
// ❌ Bad - brand-specific token
< div className = "bg-[var(--brand-primary-500)]" />
// ✅ Good - semantic token
< div className = "bg-[var(--interactive-primary)]" />
Reference component tokens for sizing
Use component tokens for consistent sizing: // ✅ Good - uses component token
< button className = "h-[var(--button-height-md)]" />
// ✅ Good - uses spacing token
< div className = "p-[var(--spacing-lg)]" />
Test in both light and dark modes
Always verify your components work in both themes: // Toggle dark mode during testing
document . documentElement . classList . add ( 'dark' );
document . documentElement . classList . remove ( 'dark' );
Use the cn() utility for class merging
Combine Tailwind classes safely with the cn() utility: import { cn } from '@/lib/utils' ;
function Component ({ className }) {
return (
< div className = { cn ( 'base-classes' , 'default-styles' , className ) } />
);
}
Next Steps
Multi-brand System Learn how to switch between brands and create custom brand themes
Customization Override tokens and customize components for your needs
Accessibility Understand how theming supports accessible design patterns
Component Library Explore all components built with the token system