Customization
GuideAll components are built on the shared token system in theme.css. Override tokens at the theme level and every component updates automatically.
How it works
Components use Tailwind utility classes that map directly to CSS custom properties — bg-bg-surface-2 compiles to background-color: var(--color-bg-surface-2). Override the token, every component reading it updates.
/* global.css — override once, propagates everywhere */
:root {
--color-bg-surface-2: #1c1c1e; /* changes Input, Dropdown, Switch track, etc. */
--radius-sm: 6px; /* changes Button, Input, Checkbox, Slider thumb… */
--color-text-primary: #a78bfa; /* changes primary Button bg, checked states… */
} For per-instance overrides use the className prop with Tailwind utilities or inline CSS vars:
import { cn } from '@forma-studio/components'
// className — always works, specific to one element
<Button.Root variant="primary" className="rounded-full px-8">
Pill button
</Button.Root>
// Scoped CSS var — overrides a token for this subtree only
<div style={{ '--color-text-primary': '#a78bfa' } as React.CSSProperties}>
<Button.Root variant="primary">Purple primary</Button.Root>
<Switch.Root>…</Switch.Root> {/* also purple */}
</div> Don't fight the system
Override tokens with other tokens, not raw values:
/* ✗ Fragile — breaks if you change the brand color later */
:root { --color-text-primary: #8b5cf6; }
/* ✓ Semantic — one source of truth */
:root {
--color-brand: #8b5cf6;
--color-text-primary: var(--color-brand); /* now everything follows brand */
} Token map — per component
Which base tokens each component reads, and what they control.
Form Controls
Button
| Token | Controls |
|---|---|
--color-text-primary | Primary variant background |
--color-text-inverted | Primary variant text |
--color-bg-surface-2 | Secondary variant background |
--color-border-subtle | Secondary variant border |
--color-error | Destructive variant background |
--color-state-hover | Ghost / outline hover fill |
--radius-sm | Border radius (all variants) |
Input · Autocomplete · Combobox · NumberField · OTPField
| Token | Controls |
|---|---|
--color-bg-surface-2 | Background |
--color-text-primary | Value text |
--color-text-muted | Placeholder text |
--color-border-subtle | Border (default state) |
--color-border-default | Border (hover state) |
--color-border-strong | Border (focused state) |
--color-error-border | Border (error state) |
--radius-sm | Border radius |
Checkbox · Radio
| Token | Controls |
|---|---|
--color-bg-surface-2 | Unchecked background |
--color-border-default | Border |
--color-text-primary | Checked background |
--color-text-inverted | Checkmark / dot color |
--radius-sm | Checkbox radius (Radio always uses --radius-full) |
Switch
| Token | Controls |
|---|---|
--color-bg-surface-3 | Track when off |
--color-text-primary | Track when on |
--color-text-muted | Thumb when off |
--color-text-inverted | Thumb when on |
Toggle · ToggleGroup
| Token | Controls |
|---|---|
--color-text-secondary | Inactive label color |
--color-text-primary | Active label color |
--color-bg-surface-3 | Active background |
--color-border-subtle | Outer border |
--color-border-default | Active item border |
--color-state-hover | Hover fill |
--radius-sm | Border radius |
Slider
| Token | Controls |
|---|---|
--color-bg-surface-3 | Track (unfilled) background |
--color-text-primary | Fill + thumb background |
--color-bg-base | Thumb inner border ring |
--shadow-sm | Thumb shadow |
Select
| Token | Controls |
|---|---|
--color-bg-surface-2 | Trigger + dropdown background |
--color-border-subtle | Trigger border (default) |
--color-border-default | Trigger border (hover) + dropdown border |
--color-state-hover | Item hover fill |
--color-state-active | Selected item fill |
--radius-sm | Trigger radius |
--radius-md | Dropdown panel radius |
--shadow-md | Dropdown panel shadow |
Field · Fieldset · Form
| Token | Controls |
|---|---|
--color-text-primary | Label text |
--color-text-secondary | Description text |
--color-error | Error message text + icon |
--color-border-subtle | Fieldset border |
--color-text-muted | Fieldset legend text |
--radius-sm | Fieldset border radius |
Overlays
Dialog · AlertDialog · Drawer
| Token | Controls |
|---|---|
--color-bg-surface-1 | Panel background |
--color-border-default | Panel border |
--color-bg-overlay | Backdrop scrim |
--radius-lg | Panel border radius |
--shadow-xl | Panel shadow |
Popover · PreviewCard
| Token | Controls |
|---|---|
--color-bg-surface-1 | Panel background |
--color-border-default | Panel border |
--radius-md | Panel border radius |
--shadow-md | Panel shadow |
Tooltip
| Token | Controls |
|---|---|
--color-bg-surface-3 | Background |
--color-text-primary | Text color |
--color-border-default | Border |
--radius-sm | Border radius |
Toast
| Token | Controls |
|---|---|
--color-bg-surface-2 | Background |
--color-border-default | Border |
--color-state-hover | Dismiss button hover fill |
--radius-md | Border radius |
--shadow-md | Shadow |
ContextMenu
| Token | Controls |
|---|---|
--color-bg-surface-2 | Menu background |
--color-border-default | Menu border |
--color-state-hover | Item hover fill |
--color-error | Destructive item text |
--color-error-bg | Destructive item hover fill |
--radius-sm | Item + menu border radius |
--shadow-md | Menu shadow |
Navigation
Menu · Menubar · NavigationMenu
| Token | Controls |
|---|---|
--color-bg-surface-1 | Menubar container background |
--color-bg-surface-2 | Popup / dropdown background |
--color-border-default | Popup border |
--color-border-subtle | Trigger border + item separators |
--color-state-hover | Trigger + item hover fill |
--color-state-active | Open / active trigger fill |
--color-text-muted | Group label text |
--radius-sm | Trigger + item radius |
--shadow-md | Popup shadow |
Tabs
| Token | Controls |
|---|---|
--color-text-secondary | Inactive tab label |
--color-text-primary | Active tab label + indicator line |
--color-border-subtle | Tab list bottom border |
--color-state-hover | Tab hover fill |
Toolbar
| Token | Controls |
|---|---|
--color-bg-surface-1 | Container background |
--color-border-subtle | Container border + separator |
--color-text-secondary | Button icon/label (inactive) |
--color-text-primary | Button icon/label (active) |
--color-state-hover | Button hover fill |
--color-state-active | Button active/pressed fill |
--radius-sm | Button border radius |
Display
Accordion · Collapsible
| Token | Controls |
|---|---|
--color-border-subtle | Divider lines between items |
--color-text-primary | Trigger label |
--color-text-secondary | Panel / content text |
--radius-sm | Chevron icon border radius |
Avatar
| Token | Controls |
|---|---|
--color-bg-surface-3 | Fallback (no image) background |
--color-text-secondary | Fallback initials color |
--color-border-subtle | Border (when shown) |
--font-display | Initials font family |
Progress · Meter
| Token | Controls |
|---|---|
--color-bg-surface-3 | Track (unfilled) background |
--color-text-primary | Fill color |
Scroll Area
| Token | Controls |
|---|---|
--color-border-default | Scrollbar thumb |
--color-border-strong | Scrollbar thumb (hover) |
Separator
| Token | Controls |
|---|---|
--color-border-subtle | Line color |
Code Preview
| Token | Controls |
|---|---|
--color-bg-surface-1 | Container background |
--color-bg-surface-2 | Tab bar background |
--color-border-default | Container border |
--color-border-subtle | Tab bar border |
--color-text-secondary | Inactive tab label |
--color-text-primary | Active tab label + code text |
--font-mono | Code font family |
--radius-sm | Container border radius |
Example — brand color
Set a single brand color and watch it propagate through every interactive component:
:root {
/* One override drives: primary Button bg, Checkbox checked state,
Switch on-track, Slider fill, active Tab indicator, Progress fill */
--color-text-primary: #8b5cf6;
/* Pair it: text on primary surfaces */
--color-text-inverted: #ffffff;
}