Stage UI Design System
All UI in apps/browser/ is built on @stagewise/stage-ui — a shared design system using OKLCH colors, Tailwind CSS 4, and Base UI (React) primitives.
Importing Styles & Components
Styles — import the CSS entry point (already done in the browser app):
@import "../../../../../packages/stage-ui/src/styles/index.css";
Components — import via package alias:
import { Button } from '@stagewise/stage-ui/components/button';
import { Tooltip, TooltipTrigger, TooltipContent } from '@stagewise/stage-ui/components/tooltip';
Utility function — cn() merges Tailwind classes (clsx + twMerge):
import { cn } from '@stagewise/stage-ui/lib/utils';
Color System (OKLCH)
All colors use OKLCH with a shared hue --H: 265 (purple). The palette is defined in palette.css.
Base colors (--color-base-50 to --color-base-950): Low-chroma, nearly grayscale but subtly tinted. Used for 95%+ of the app.
Primary colors (--color-primary-50 to --color-primary-950): High-chroma, saturated. Used for CTAs, links, active states.
Semantic colors: success (green), error (red), warning (yellow), info (blue) — each has -background, -foreground, -solid variants that auto-switch with light/dark.
Theme Tokens
Defined in theme.css, tokens auto-switch between light and dark mode via prefers-color-scheme.
Backgrounds
| Tailwind class |
Token |
Usage |
bg-app-background |
--color-app-background |
Outermost app chrome |
bg-background |
--color-background |
Main content areas, cards, panels |
bg-surface-1 |
--color-surface-1 |
First elevation above background |
bg-surface-2 |
--color-surface-2 |
Second elevation (nested elements) |
bg-surface-3 |
--color-surface-3 |
Third elevation (deeply nested) |
bg-surface-tinted |
--color-surface-tinted |
Primary-tinted highlight surface |
bg-overlay |
--color-overlay |
Modal/dialog backdrops (use with opacity) |
Text
| Tailwind class |
Usage |
text-foreground |
Primary readable text |
text-muted-foreground |
Secondary/less important text |
text-subtle-foreground |
Hints, placeholders, disabled text |
text-primary-foreground |
Accent text (links, highlights) |
text-solid-foreground |
Text on solid/primary backgrounds |
Borders
| Tailwind class |
Usage |
border-border |
Regular borders |
border-border-subtle |
Subtle/lighter borders |
Primary
| Tailwind class |
Usage |
bg-primary-solid |
Solid primary fill (buttons, badges) |
Semantic
Pattern: (bg|text)-{success|error|warning|info}-{background|foreground|solid}
Elevation & Shadows
Light mode: Use bg-background for cards. Depth comes from shadows.
Dark mode: Use escalating surfaces based on nesting depth:
- Element on
bg-background → use bg-surface-1
- Element on
bg-surface-1 → use bg-surface-2
- Element on
bg-surface-2 → use bg-surface-3
Shadow utilities (defined in shadows.css):
shadow-elevation-1 — subtle card shadow
shadow-elevation-2 — prominent popup/modal shadow
Derived Utilities
These auto-derive border/hover/active colors from an element's background. Requires the element to have a bg-* class set.
Borders (derived from background)
border-derived-subtle — light border
border-derived — regular border
border-derived-strong — strong border
border-derived-lighter-subtle / border-derived-lighter — explicitly lighter
Same pattern for rings: ring-derived-subtle, ring-derived, ring-derived-strong
Hover & Active States
hover:bg-hover-derived — hover background
active:bg-active-derived — active/pressed background
hover:text-hover-derived — hover text
active:text-active-derived — active text
Explicit Lighten/Darken (ignores dark/light mode)
bg-derived-lighter / bg-derived-lighter-subtle
bg-derived-darker / bg-derived-darker-subtle
text-derived-lighter / text-derived-lighter-subtle
Animations
Defined in animations.css. Use as Tailwind classes:
| Class |
Effect |
animate-progress-bar-indicator |
Repeating slide for progress bars |
animate-skeleton-shimmer |
Loading shimmer for skeletons |
animate-caret-blink |
Blinking caret for inputs |
animate-icon-pulse |
Stroke-width pulse for icons |
animate-pulse-full |
Full opacity pulse (0→1→0) |
animate-text-pulse |
Muted↔foreground text pulse |
animate-text-pulse-warning |
Foreground↔warning text pulse |
shimmer-text |
Shimmering gradient text effect |
shimmer-text-primary |
Primary-colored shimmer preset |
shimmer-text-once |
One-shot shimmer that settles |
Shimmer config: shimmer-duration-{ms}, shimmer-from-{color}, shimmer-to-{color}
Component Patterns
All components follow these patterns:
- Built on Base UI (
@base-ui/react) — unstyled React primitives
- Variants via CVA (
class-variance-authority) — variant and size props
- Class merging via
cn() — all accept className for overrides
- Compound components — e.g.
Dialog + DialogContent + DialogTitle
Typical usage example
import { Button } from '@stagewise/stage-ui/components/button';
import { Tooltip, TooltipTrigger, TooltipContent } from '@stagewise/stage-ui/components/tooltip';
<Tooltip>
<TooltipTrigger>
<Button variant="secondary" size="sm">Click me</Button>
</TooltipTrigger>
<TooltipContent side="top">Helpful hint</TooltipContent>
</Tooltip>
Available Components
For detailed API and props of each component, see components-reference.md.
| Component |
Import path |
Key props |
| Button |
components/button |
variant: primary, secondary, destructive, warning, success, ghost. size: xs, sm, md, lg, icon-2xs, icon-xs, icon-sm, icon-md |
| Input |
components/input |
size: xs, sm, md. debounce: ms. Built on Base UI Input |
| Select |
components/select |
items, value, onValueChange, size, triggerVariant: ghost/secondary, multiple |
| Checkbox |
components/checkbox |
size: xs, sm, md. Built on Base UI Checkbox |
| Switch |
components/switch |
size: xs, sm, md. Built on Base UI Switch |
| Radio |
components/radio |
RadioGroup + Radio + RadioLabel. Built on Base UI Radio |
| Tabs |
components/tabs |
Tabs, TabsList, TabsTrigger, TabsContent |
| Dialog |
components/dialog |
Dialog, DialogTrigger, DialogContent, DialogTitle, DialogDescription, DialogClose, DialogHeader, DialogFooter |
| Popover |
components/popover |
Popover, PopoverTrigger, PopoverContent, PopoverTitle, PopoverDescription, PopoverClose, PopoverFooter |
| Tooltip |
components/tooltip |
Tooltip, TooltipTrigger, TooltipContent, TooltipProvider |
| Menu |
components/menu |
Menu, MenuTrigger, MenuContent, MenuItem, MenuSeparator, MenuSubmenu, MenuSubmenuTrigger, MenuSubmenuContent |
| Collapsible |
components/collapsible |
Collapsible, CollapsibleTrigger (size: default/condensed), CollapsibleContent |
| Progress |
components/progress |
Progress, ProgressTrack (variant: normal/warning, busy, slim), ProgressLabel, ProgressValue |
| Skeleton |
components/skeleton |
variant: rectangle, circle, text. size: xs–full. animate: boolean |
| Form |
components/form |
Form, FormFieldset, FormField, FormFieldLabel, FormFieldTitle, FormFieldDescription, FormFieldError, FormFieldSeparator |
| Resizable |
components/resizable |
ResizablePanelGroup, ResizablePanel, ResizableHandle. Built on react-resizable-panels |
| OverlayScrollbar |
components/overlay-scrollbar |
Custom scrollbar wrapper |
| Toaster |
components/toaster |
Toast notification system |
| Breadcrumb |
components/breadcrumb |
Breadcrumb navigation |
| Combobox |
components/combobox |
Combobox/autocomplete input |
| InputOtp |
components/input-otp |
OTP code input |
| SearchableSelect |
components/searchable-select |
Searchable dropdown select |
| SplitText |
components/split-text |
Text splitting utility |
| PreviewCard |
components/preview-card |
Card with preview content |
| LogoText |
components/logo-text |
Stagewise logo text |
Quick Decision Guide
Picking a background:
- Top-level page →
bg-app-background
- Card/panel →
bg-background
- Nested element → escalate:
bg-surface-1 → bg-surface-2 → bg-surface-3
Picking text color:
- Primary content →
text-foreground
- Secondary info →
text-muted-foreground
- Placeholder/disabled →
text-subtle-foreground
- Links/accents →
text-primary-foreground
Borders & states (on elements with bg-*):
- Border:
border border-derived or border border-derived-subtle
- Hover:
hover:bg-hover-derived
- Active:
active:bg-active-derived
Icons: Use lucide-react or nucleo-ui-fill-18 (project-specific icon set).
Storybook
Preview components and color definitions:
pnpm --filter stagewise storybook
1---2name: stage-ui-design-system3description: Stagewise UI theming, design tokens, derived utilities, and component library reference. Use when creating, editing, or reviewing UI in apps/browser, implementing new screens or components, or styling with Tailwind in the stagewise codebase.4---56# Stage UI Design System78All UI in `apps/browser/` is built on `@stagewise/stage-ui` — a shared design system using **OKLCH colors**, **Tailwind CSS 4**, and **Base UI (React)** primitives.910## Importing Styles & Components1112**Styles** — import the CSS entry point (already done in the browser app):13```css14@import "../../../../../packages/stage-ui/src/styles/index.css";15```1617**Components** — import via package alias:18```tsx19import { Button } from '@stagewise/stage-ui/components/button';20import { Tooltip, TooltipTrigger, TooltipContent } from '@stagewise/stage-ui/components/tooltip';21```2223**Utility function** — `cn()` merges Tailwind classes (clsx + twMerge):24```tsx25import { cn } from '@stagewise/stage-ui/lib/utils';26```2728## Color System (OKLCH)2930All colors use OKLCH with a shared hue `--H: 265` (purple). The palette is defined in `palette.css`.3132**Base colors** (`--color-base-50` to `--color-base-950`): Low-chroma, nearly grayscale but subtly tinted. Used for 95%+ of the app.3334**Primary colors** (`--color-primary-50` to `--color-primary-950`): High-chroma, saturated. Used for CTAs, links, active states.3536**Semantic colors**: `success` (green), `error` (red), `warning` (yellow), `info` (blue) — each has `-background`, `-foreground`, `-solid` variants that auto-switch with light/dark.3738## Theme Tokens3940Defined in `theme.css`, tokens auto-switch between light and dark mode via `prefers-color-scheme`.4142### Backgrounds4344| Tailwind class | Token | Usage |45|---|---|---|46| `bg-app-background` | `--color-app-background` | Outermost app chrome |47| `bg-background` | `--color-background` | Main content areas, cards, panels |48| `bg-surface-1` | `--color-surface-1` | First elevation above background |49| `bg-surface-2` | `--color-surface-2` | Second elevation (nested elements) |50| `bg-surface-3` | `--color-surface-3` | Third elevation (deeply nested) |51| `bg-surface-tinted` | `--color-surface-tinted` | Primary-tinted highlight surface |52| `bg-overlay` | `--color-overlay` | Modal/dialog backdrops (use with opacity) |5354### Text5556| Tailwind class | Usage |57|---|---|58| `text-foreground` | Primary readable text |59| `text-muted-foreground` | Secondary/less important text |60| `text-subtle-foreground` | Hints, placeholders, disabled text |61| `text-primary-foreground` | Accent text (links, highlights) |62| `text-solid-foreground` | Text on solid/primary backgrounds |6364### Borders6566| Tailwind class | Usage |67|---|---|68| `border-border` | Regular borders |69| `border-border-subtle` | Subtle/lighter borders |7071### Primary7273| Tailwind class | Usage |74|---|---|75| `bg-primary-solid` | Solid primary fill (buttons, badges) |7677### Semantic7879Pattern: `(bg|text)-{success|error|warning|info}-{background|foreground|solid}`8081## Elevation & Shadows8283**Light mode**: Use `bg-background` for cards. Depth comes from shadows.84**Dark mode**: Use escalating surfaces based on nesting depth:85- Element on `bg-background` → use `bg-surface-1`86- Element on `bg-surface-1` → use `bg-surface-2`87- Element on `bg-surface-2` → use `bg-surface-3`8889Shadow utilities (defined in `shadows.css`):90- `shadow-elevation-1` — subtle card shadow91- `shadow-elevation-2` — prominent popup/modal shadow9293## Derived Utilities9495These auto-derive border/hover/active colors from an element's background. **Requires the element to have a `bg-*` class set.**9697### Borders (derived from background)98- `border-derived-subtle` — light border99- `border-derived` — regular border100- `border-derived-strong` — strong border101- `border-derived-lighter-subtle` / `border-derived-lighter` — explicitly lighter102103Same pattern for rings: `ring-derived-subtle`, `ring-derived`, `ring-derived-strong`104105### Hover & Active States106- `hover:bg-hover-derived` — hover background107- `active:bg-active-derived` — active/pressed background108- `hover:text-hover-derived` — hover text109- `active:text-active-derived` — active text110111### Explicit Lighten/Darken (ignores dark/light mode)112- `bg-derived-lighter` / `bg-derived-lighter-subtle`113- `bg-derived-darker` / `bg-derived-darker-subtle`114- `text-derived-lighter` / `text-derived-lighter-subtle`115116## Animations117118Defined in `animations.css`. Use as Tailwind classes:119120| Class | Effect |121|---|---|122| `animate-progress-bar-indicator` | Repeating slide for progress bars |123| `animate-skeleton-shimmer` | Loading shimmer for skeletons |124| `animate-caret-blink` | Blinking caret for inputs |125| `animate-icon-pulse` | Stroke-width pulse for icons |126| `animate-pulse-full` | Full opacity pulse (0→1→0) |127| `animate-text-pulse` | Muted↔foreground text pulse |128| `animate-text-pulse-warning` | Foreground↔warning text pulse |129| `shimmer-text` | Shimmering gradient text effect |130| `shimmer-text-primary` | Primary-colored shimmer preset |131| `shimmer-text-once` | One-shot shimmer that settles |132133Shimmer config: `shimmer-duration-{ms}`, `shimmer-from-{color}`, `shimmer-to-{color}`134135## Component Patterns136137All components follow these patterns:1381391. **Built on Base UI** (`@base-ui/react`) — unstyled React primitives1402. **Variants via CVA** (`class-variance-authority`) — `variant` and `size` props1413. **Class merging** via `cn()` — all accept `className` for overrides1424. **Compound components** — e.g. `Dialog` + `DialogContent` + `DialogTitle`143144### Typical usage example145146```tsx147import { Button } from '@stagewise/stage-ui/components/button';148import { Tooltip, TooltipTrigger, TooltipContent } from '@stagewise/stage-ui/components/tooltip';149150<Tooltip>151 <TooltipTrigger>152 <Button variant="secondary" size="sm">Click me</Button>153 </TooltipTrigger>154 <TooltipContent side="top">Helpful hint</TooltipContent>155</Tooltip>156```157158## Available Components159160For detailed API and props of each component, see [components-reference.md](components-reference.md).161162| Component | Import path | Key props |163|---|---|---|164| **Button** | `components/button` | `variant`: primary, secondary, destructive, warning, success, ghost. `size`: xs, sm, md, lg, icon-2xs, icon-xs, icon-sm, icon-md |165| **Input** | `components/input` | `size`: xs, sm, md. `debounce`: ms. Built on Base UI Input |166| **Select** | `components/select` | `items`, `value`, `onValueChange`, `size`, `triggerVariant`: ghost/secondary, `multiple` |167| **Checkbox** | `components/checkbox` | `size`: xs, sm, md. Built on Base UI Checkbox |168| **Switch** | `components/switch` | `size`: xs, sm, md. Built on Base UI Switch |169| **Radio** | `components/radio` | `RadioGroup` + `Radio` + `RadioLabel`. Built on Base UI Radio |170| **Tabs** | `components/tabs` | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent` |171| **Dialog** | `components/dialog` | `Dialog`, `DialogTrigger`, `DialogContent`, `DialogTitle`, `DialogDescription`, `DialogClose`, `DialogHeader`, `DialogFooter` |172| **Popover** | `components/popover` | `Popover`, `PopoverTrigger`, `PopoverContent`, `PopoverTitle`, `PopoverDescription`, `PopoverClose`, `PopoverFooter` |173| **Tooltip** | `components/tooltip` | `Tooltip`, `TooltipTrigger`, `TooltipContent`, `TooltipProvider` |174| **Menu** | `components/menu` | `Menu`, `MenuTrigger`, `MenuContent`, `MenuItem`, `MenuSeparator`, `MenuSubmenu`, `MenuSubmenuTrigger`, `MenuSubmenuContent` |175| **Collapsible** | `components/collapsible` | `Collapsible`, `CollapsibleTrigger` (size: default/condensed), `CollapsibleContent` |176| **Progress** | `components/progress` | `Progress`, `ProgressTrack` (variant: normal/warning, busy, slim), `ProgressLabel`, `ProgressValue` |177| **Skeleton** | `components/skeleton` | `variant`: rectangle, circle, text. `size`: xs–full. `animate`: boolean |178| **Form** | `components/form` | `Form`, `FormFieldset`, `FormField`, `FormFieldLabel`, `FormFieldTitle`, `FormFieldDescription`, `FormFieldError`, `FormFieldSeparator` |179| **Resizable** | `components/resizable` | `ResizablePanelGroup`, `ResizablePanel`, `ResizableHandle`. Built on react-resizable-panels |180| **OverlayScrollbar** | `components/overlay-scrollbar` | Custom scrollbar wrapper |181| **Toaster** | `components/toaster` | Toast notification system |182| **Breadcrumb** | `components/breadcrumb` | Breadcrumb navigation |183| **Combobox** | `components/combobox` | Combobox/autocomplete input |184| **InputOtp** | `components/input-otp` | OTP code input |185| **SearchableSelect** | `components/searchable-select` | Searchable dropdown select |186| **SplitText** | `components/split-text` | Text splitting utility |187| **PreviewCard** | `components/preview-card` | Card with preview content |188| **LogoText** | `components/logo-text` | Stagewise logo text |189190## Quick Decision Guide191192**Picking a background:**193- Top-level page → `bg-app-background`194- Card/panel → `bg-background`195- Nested element → escalate: `bg-surface-1` → `bg-surface-2` → `bg-surface-3`196197**Picking text color:**198- Primary content → `text-foreground`199- Secondary info → `text-muted-foreground`200- Placeholder/disabled → `text-subtle-foreground`201- Links/accents → `text-primary-foreground`202203**Borders & states (on elements with `bg-*`):**204- Border: `border border-derived` or `border border-derived-subtle`205- Hover: `hover:bg-hover-derived`206- Active: `active:bg-active-derived`207208**Icons:** Use `lucide-react` or `nucleo-ui-fill-18` (project-specific icon set).209210## Storybook211212Preview components and color definitions:213```bash214pnpm --filter stagewise storybook215```