Theming
Customize the design system with CSS custom properties
Playground
Card Title
Cards, badges, and tags all respond to the same core tokens.
Primary
Success
Warning
Danger
Tag
const theme = "custom"
Info alert
Success alert
Warning alert
Danger alert
<!-- Drag the sliders to see how core tokens cascade through the entire system. Every component on this page responds in real time. -->
<div id="theme-playground">
<div class="demo-playground">
<div class="demo-playground__row">
<label>scale</label>
<input class="ui-slider ui-slider--sm" type="range" min="0.75" max="1.25" step="0.025" value="1" data-token="--ui-scale" data-suffix="">
<output>1</output>
</div>
<div class="demo-playground__row">
<label>primary hue</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="360" step="1" value="250" data-token="--ui-color-primary" data-template="oklch(55% 0.22 {value})" data-suffix="">
<output>250</output>
</div>
<div class="demo-playground__row">
<label>success hue</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="360" step="1" value="145" data-token="--ui-color-success" data-template="oklch(60% 0.18 {value})" data-suffix="">
<output>145</output>
</div>
<div class="demo-playground__row">
<label>warning hue</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="360" step="1" value="70" data-token="--ui-color-warning" data-template="oklch(75% 0.18 {value})" data-suffix="">
<output>70</output>
</div>
<div class="demo-playground__row">
<label>danger hue</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="360" step="1" value="25" data-token="--ui-color-danger" data-template="oklch(60% 0.22 {value})" data-suffix="">
<output>25</output>
</div>
<div class="demo-playground__row">
<label>neutral hue</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="360" step="1" value="250" data-token="--ui-color-neutral" data-param="hue" data-template="oklch(50% {chroma} {hue})" data-suffix="">
<output>250</output>
</div>
<div class="demo-playground__row">
<label>neutral chroma</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="0.08" step="0.005" value="0.02" data-token="--ui-color-neutral" data-param="chroma" data-template="oklch(50% {chroma} {hue})" data-suffix="">
<output>0.02</output>
</div>
<div class="demo-playground__row">
<label>font size</label>
<input class="ui-slider ui-slider--sm" type="range" min="0.75" max="1.25" step="0.05" value="1" data-token="--ui-font-size-base" data-suffix="rem">
<output>1rem</output>
</div>
<div class="demo-playground__row">
<label>font family</label>
<select class="ui-select ui-select--sm" data-token="--ui-font-sans">
<option value="system-ui, -apple-system, sans-serif">System</option>
<option value="'Georgia', 'Times New Roman', serif">Serif</option>
<option value="ui-monospace, sfmono-regular, monospace">Mono</option>
<option value="'Noto Sans', system-ui, sans-serif">Noto Sans</option>
</select>
<output></output>
</div>
<div class="demo-playground__row">
<label>mono font</label>
<select class="ui-select ui-select--sm" data-token="--ui-font-mono">
<option value="ui-monospace, sfmono-regular, monospace">System</option>
<option value="'Courier New', courier, monospace">Courier</option>
<option value="'Fira Code', ui-monospace, monospace">Fira Code</option>
</select>
<output></output>
</div>
<div class="demo-playground__row">
<label>radius</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="24" step="1" value="8" data-token="--ui-radius-base" data-suffix="px">
<output>8px</output>
</div>
<div class="demo-playground__row">
<label>shadow strength</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="40" step="1" value="20" data-token="--ui-shadow-strength" data-suffix="%">
<output>20%</output>
</div>
<div class="demo-playground__row">
<label>border width</label>
<input class="ui-slider ui-slider--sm" type="range" min="0" max="4" step="0.5" value="1" data-token="--ui-border-width-base" data-suffix="px">
<output>1px</output>
</div>
<div class="ui-row ui-row--xs">
<button class="ui-button ui-button--sm ui-button--secondary" data-reset>Reset</button>
<button class="ui-button ui-button--sm" data-random>Random Theme</button>
</div>
</div>
<div class="demo-playground__preview">
<div class="ui-row ui-row--xs">
<span class="demo-swatch-color demo-swatch-color--primary"></span>
<span class="demo-swatch-color demo-swatch-color--success"></span>
<span class="demo-swatch-color demo-swatch-color--warning"></span>
<span class="demo-swatch-color demo-swatch-color--danger"></span>
<span class="demo-swatch-color demo-swatch-color--neutral"></span>
</div>
<div class="ui-row ui-row--xs">
<button class="ui-button">Primary</button>
<button class="ui-button ui-button--secondary">Secondary</button>
<button class="ui-button ui-button--danger">Danger</button>
</div>
<div class="ui-row ui-row--xs">
<button class="ui-button ui-button--sm">Small</button>
<button class="ui-button ui-button--lg">Large</button>
</div>
<input class="ui-input" placeholder="Type here...">
<select class="ui-select">
<option>Select option</option>
</select>
<div class="ui-card">
<h4 class="ui-heading">Card Title</h4>
<p>Cards, badges, and tags all respond to the same core tokens.</p>
<div class="ui-row ui-row--xs">
<span class="ui-badge ui-badge--primary">Primary</span>
<span class="ui-badge ui-badge--success">Success</span>
<span class="ui-badge ui-badge--warning">Warning</span>
<span class="ui-badge ui-badge--danger">Danger</span>
<span class="ui-tag">Tag</span>
</div>
</div>
<div class="ui-row ui-row--xs">
<input class="ui-slider" type="range" min="0" max="100" value="60">
<div class="ui-toggle">
<input class="ui-toggle__input" type="checkbox" checked>
<span class="ui-toggle__track"></span>
<span class="ui-toggle__thumb"></span>
</div>
</div>
<div class="ui-progress" role="progressbar" aria-valuenow="65" aria-valuemin="0" aria-valuemax="100" style="--ui-progress-value: 65%">
<div class="ui-progress__bar"></div>
</div>
<code class="ui-code">const theme = "custom"</code>
<div class="ui-column ui-column--xs">
<div class="ui-alert ui-alert--info">Info alert</div>
<div class="ui-alert ui-alert--success">Success alert</div>
<div class="ui-alert ui-alert--warning">Warning alert</div>
<div class="ui-alert ui-alert--danger">Danger alert</div>
</div>
</div>
</div>
Brand Colors
<!-- Override --ui-color-primary to change the entire color palette. All shades (light, dark, subtle, hover) derive automatically via color-mix(). -->
<div class="demo-theme">
<button class="ui-button">Primary</button>
<button class="ui-button ui-button--secondary">Secondary</button>
<button class="ui-button ui-button--danger">Danger</button>
</div>
<div class="demo-theme demo-theme--purple">
<button class="ui-button">Primary</button>
<button class="ui-button ui-button--secondary">Secondary</button>
<button class="ui-button ui-button--danger">Danger</button>
</div>
<div class="demo-theme demo-theme--teal">
<button class="ui-button">Primary</button>
<button class="ui-button ui-button--secondary">Secondary</button>
<button class="ui-button ui-button--danger">Danger</button>
</div>
<div class="demo-theme demo-theme--orange">
<button class="ui-button">Primary</button>
<button class="ui-button ui-button--secondary">Secondary</button>
<button class="ui-button ui-button--danger">Danger</button>
</div>
Radius Theming
radius-base: 0
radius-base: 0.5rem
radius-base: 1rem
<!-- Override --ui-radius-base to control all corner radii at once. Set to 0 for sharp corners or increase for a softer look. sm/md/lg derive automatically via calc(). -->
<div class="demo-theme demo-theme--sharp">
<button class="ui-button">Sharp</button>
<div class="ui-card">
<p>radius-base: 0</p>
</div>
</div>
<div class="demo-theme">
<button class="ui-button">Default</button>
<div class="ui-card">
<p>radius-base: 0.5rem</p>
</div>
</div>
<div class="demo-theme demo-theme--round">
<button class="ui-button">Round</button>
<div class="ui-card">
<p>radius-base: 1rem</p>
</div>
</div>
Dark Mode
Follows OS color scheme
Always light
Always dark
<!-- Dark mode uses the CSS light-dark() function. Tokens resolve automatically based on color-scheme. Override with data-theme attribute. -->
<div class="demo-theme">
<div class="ui-card">
<p>Follows OS color scheme</p>
</div>
</div>
<div class="demo-theme" data-theme="light">
<div class="ui-card">
<p>Always light</p>
</div>
</div>
<div class="demo-theme" data-theme="dark">
<div class="ui-card">
<p>Always dark</p>
</div>
</div>
Full Theme Examples
Corporate: teal, sharp corners, system font
Playful: orange, round corners
Minimal: neutral palette, no radius
<!-- Complete theme customization using just 2-3 root tokens. -->
<div class="demo-theme demo-theme--corporate">
<button class="ui-button">Action</button>
<div class="ui-card">
<p>Corporate: teal, sharp corners, system font</p>
</div>
</div>
<div class="demo-theme demo-theme--playful">
<button class="ui-button">Action</button>
<div class="ui-card">
<p>Playful: orange, round corners</p>
</div>
</div>
<div class="demo-theme demo-theme--minimal">
<button class="ui-button">Action</button>
<div class="ui-card">
<p>Minimal: neutral palette, no radius</p>
</div>
</div>
Component Overrides
Card with custom padding
<!-- Override specific component tokens for fine-grained control. -->
<div class="demo-theme demo-buttons">
<button class="ui-button ui-button--sm">Small</button>
<button class="ui-button">Default</button>
<button class="ui-button ui-button--lg">Large</button>
</div>
<div class="demo-theme demo-cards">
<div class="ui-card">
<p>Card with custom padding</p>
</div>
</div>