Theming
spacing-ui components are unstyled. You can theme them with any styling solution you already use.
CSS custom properties
Because everything is a plain HTML element, CSS custom properties work out of the box. Define your tokens on :root and use them in your component styles.
:root {
--sui-radius: 0.5rem;
--sui-bg: #ffffff;
--sui-fg: #111827;
--sui-accent: #2563eb;
}
[data-state="open"] {
background: var(--sui-bg);
}Every primitive sets data-state, data-orientation, and data-disabled attributes you can hook into.
Tailwind CSS
Attribute selectors compose cleanly with Tailwind variants. Add a plugin (or use @variant) to expose them:
<Dialog.Content className="rounded-md bg-white shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out">
...
</Dialog.Content>Combine with data-orientation for orientation-aware styling on tabs, radio groups, and separators.
CSS Modules
Pass a className to any part; sub-parts accept className too. State-driven styles use attribute selectors inside the module:
.trigger { padding: 0.5rem 1rem; }
.trigger[data-state="open"] { background: var(--sui-accent); }<Accordion.Trigger className={styles.trigger}>...</Accordion.Trigger>Design tokens
The docs site ships a small set of CSS custom properties in app/globals.css. They cover surfaces, text, borders, an indigo accent, radii, spacing, elevation shadows, and motion timing:
:root {
--sui-color-accent: #4f46e5;
--sui-color-accent-soft: #eef2ff;
--sui-radius-md: 8px;
--sui-shadow-lg: 0 20px 40px rgba(15, 23, 42, 0.18);
--sui-duration: 180ms;
--sui-ease: cubic-bezier(0.16, 1, 0.3, 1);
}Override any of these on :root, on a parent element, or per component to reskin the entire demo surface.
Animations
Reusable keyframes live alongside the tokens:
sui-fade-in— opacity 0 → 1sui-scale-in— opacity + subtle scale, for popovers and dialogssui-slide-down-fade— for menus and tooltipssui-check-in— for check marks and radio dots
Wire them up with data-state attribute selectors so entry and exit animations follow the component’s own state:
.dialog-content[data-state="open"] {
animation: sui-scale-in var(--sui-duration) var(--sui-ease);
}