decocms product design system (@decocms/ui)
React 19 components built on Radix primitives, styled with Tailwind CSS v4
semantic tokens. Light and dark themes work out of the box. Browse every
component and token at https://designsystem.decocms.com/
Install (new project)
bun add @decocms/ui react react-dom
Requirements: React 19 and Tailwind CSS v4 (bun add -d tailwindcss @tailwindcss/vite
plus the tailwindcss() plugin in vite.config.ts).
Make the design-system stylesheet the FIRST import of the app's CSS entry point —
it pulls in Tailwind itself, all tokens, and the bundled fonts (Inter + Commit Mono).
Do NOT also @import "tailwindcss" yourself:
@import "@decocms/ui/styles/global.css";
Tailwind only scans app source by default; if the app's classes come exclusively
from @decocms/ui components this already works — the package declares its own
@source.
Peers: install react-hook-form if you use the form component, and sonner
if you use toasts (sonner component). They are peers so the app and the design
system share one instance — never bundle a second copy.
Imports
No barrel export. Import each component from its subpath, extensionless:
import { Button } from "@decocms/ui/components/button";
import { Dialog, DialogContent, DialogTrigger } from "@decocms/ui/components/dialog";
import { cn } from "@decocms/ui/lib/utils";
import { useIsMobile } from "@decocms/ui/hooks/use-mobile";
Exception — inside the decocms/studio monorepo, workspace imports keep the
source extension: @decocms/ui/components/button.tsx.
Rules
- Semantic tokens only, never raw palette.
bg-primary, text-muted-foreground,
bg-destructive, border-border — never bg-red-500 or text-zinc-400.
Available color roles: background, foreground, card, popover, primary,
secondary, muted, accent, destructive, success, warning, special
(AI/highlight moments), brand, border, input, ring, sidebar-*
(sidebar surfaces), chart-1..5 (data viz). Most roles pair with a
*-foreground text token.
- Dark mode is automatic via the
.dark class on a root element — never
hardcode colors or write dark: overrides that bypass tokens.
- Compose, don't fork. Extend components with
className + cn(); add
variants through the component's cva config rather than wrapping with
custom styles.
font-bold renders at weight 650 (custom scale); body text is 450.
Radius scale derives from --radius (default 0.375rem).
- User-facing copy comes from the app, passed as props — components ship
only overridable English defaults.
Component inventory
- Forms: button, input, textarea, label, checkbox, radio-group, switch,
slider, select, form (react-hook-form), input-otp, password-input,
datetime-input, email-tags-input, multi-select, search-input, combobox,
time-range-picker
- Overlays: dialog, alert-dialog, sheet, drawer, popover, hover-card,
tooltip, command (palette), context-menu, dropdown-menu, menubar,
responsive-dropdown, responsive-select (desktop/mobile adaptive)
- Feedback: alert, badge, progress, skeleton, spinner, sonner (toasts),
empty-state, empty-state-illustrations
- Layout & navigation: card, separator, tabs, accordion, collapsible,
breadcrumb, navigation-menu, pagination, scroll-area, aspect-ratio, table,
sidebar (full app sidebar system), sidebar-footer-shell, app-topbar,
topbar-switcher, user-menu, step-indicator
- Data & content: avatar, calendar, carousel, chart (recharts + chart tokens),
markdown, entity-card, entity-grid, filter-bar, collection-search,
view-mode-toggle, button-group, toggle, toggle-group
Before using a component, read its source in node_modules/@decocms/ui/src/components/<name>.tsx
(shipped in the package) to see its exact exports and props, or check its page
in the Storybook.
Icons
Components use @untitledui/icons (comes as a dependency). Prefer it in
consuming apps for visual consistency:
import { Plus, SearchMd, Trash01 } from "@untitledui/icons";
1---2name: decocms-ui3description: Build or style React UI with the decocms product design system (@decocms/ui). Use when creating interfaces, pages, or components in a project that should look like decocms products, when the user mentions "design system", "@decocms/ui", "decocms style", or asks to make UI consistent with Studio. Covers installation, Tailwind v4 token setup, component inventory, and usage conventions.4---56# decocms product design system (@decocms/ui)78React 19 components built on Radix primitives, styled with Tailwind CSS v49semantic tokens. Light and dark themes work out of the box. Browse every10component and token at https://designsystem.decocms.com/1112## Install (new project)1314```bash15bun add @decocms/ui react react-dom16```1718Requirements: React 19 and Tailwind CSS v4 (`bun add -d tailwindcss @tailwindcss/vite`19plus the `tailwindcss()` plugin in `vite.config.ts`).2021Make the design-system stylesheet the FIRST import of the app's CSS entry point —22it pulls in Tailwind itself, all tokens, and the bundled fonts (Inter + Commit Mono).23Do NOT also `@import "tailwindcss"` yourself:2425```css26@import "@decocms/ui/styles/global.css";27```2829Tailwind only scans app source by default; if the app's classes come exclusively30from @decocms/ui components this already works — the package declares its own31`@source`.3233Peers: install `react-hook-form` if you use the `form` component, and `sonner`34if you use toasts (`sonner` component). They are peers so the app and the design35system share one instance — never bundle a second copy.3637## Imports3839No barrel export. Import each component from its subpath, extensionless:4041```tsx42import { Button } from "@decocms/ui/components/button";43import { Dialog, DialogContent, DialogTrigger } from "@decocms/ui/components/dialog";44import { cn } from "@decocms/ui/lib/utils";45import { useIsMobile } from "@decocms/ui/hooks/use-mobile";46```4748Exception — inside the decocms/studio monorepo, workspace imports keep the49source extension: `@decocms/ui/components/button.tsx`.5051## Rules52531. **Semantic tokens only, never raw palette.** `bg-primary`, `text-muted-foreground`,54 `bg-destructive`, `border-border` — never `bg-red-500` or `text-zinc-400`.55 Available color roles: `background`, `foreground`, `card`, `popover`, `primary`,56 `secondary`, `muted`, `accent`, `destructive`, `success`, `warning`, `special`57 (AI/highlight moments), `brand`, `border`, `input`, `ring`, `sidebar-*`58 (sidebar surfaces), `chart-1..5` (data viz). Most roles pair with a59 `*-foreground` text token.602. **Dark mode is automatic** via the `.dark` class on a root element — never61 hardcode colors or write `dark:` overrides that bypass tokens.623. **Compose, don't fork.** Extend components with `className` + `cn()`; add63 variants through the component's `cva` config rather than wrapping with64 custom styles.654. **`font-bold` renders at weight 650** (custom scale); body text is 450.66 Radius scale derives from `--radius` (default 0.375rem).675. **User-facing copy comes from the app**, passed as props — components ship68 only overridable English defaults.6970## Component inventory7172- **Forms**: button, input, textarea, label, checkbox, radio-group, switch,73 slider, select, form (react-hook-form), input-otp, password-input,74 datetime-input, email-tags-input, multi-select, search-input, combobox,75 time-range-picker76- **Overlays**: dialog, alert-dialog, sheet, drawer, popover, hover-card,77 tooltip, command (palette), context-menu, dropdown-menu, menubar,78 responsive-dropdown, responsive-select (desktop/mobile adaptive)79- **Feedback**: alert, badge, progress, skeleton, spinner, sonner (toasts),80 empty-state, empty-state-illustrations81- **Layout & navigation**: card, separator, tabs, accordion, collapsible,82 breadcrumb, navigation-menu, pagination, scroll-area, aspect-ratio, table,83 sidebar (full app sidebar system), sidebar-footer-shell, app-topbar,84 topbar-switcher, user-menu, step-indicator85- **Data & content**: avatar, calendar, carousel, chart (recharts + chart tokens),86 markdown, entity-card, entity-grid, filter-bar, collection-search,87 view-mode-toggle, button-group, toggle, toggle-group8889Before using a component, read its source in `node_modules/@decocms/ui/src/components/<name>.tsx`90(shipped in the package) to see its exact exports and props, or check its page91in the Storybook.9293## Icons9495Components use `@untitledui/icons` (comes as a dependency). Prefer it in96consuming apps for visual consistency:9798```tsx99import { Plus, SearchMd, Trash01 } from "@untitledui/icons";100```