Westy Design Systemv0.2.7
OverviewComponentsExamplesStorybook

The shared foundation for building Westy products

Design tokens, components and conventions that keep designers and engineers speaking the same language — from Figma to production in WestyApp.

60 components4 color scalesLight & darkRTL-ready
Browse componentsSee examples

Press D anywhere to toggle dark mode.

How to use it

One system, three audiences. The tokens, variants and import surface below are the shared contract.

Designers
The semantic tokens are the contract.

Every color, radius and type decision here has a name. Design with those names — primary, muted, destructive — and dark mode comes for free, because each token remaps itself.

If the token you need doesn't exist, the fix is a new token — never a hardcoded color.

Frontend engineers
Import the exact module — no barrel file.
import { Button } from
  "@workspace/ui/components/button"

The release branch ships compiled ESM and TypeScript declarations. react, react-dom and next-themes are peer dependencies: your app owns the single copy.

Backend engineers
Variants are product vocabulary.

Component variants and states — default | secondary | destructive | outline — are shared vocabulary. When an enum or payload maps a status to one of these names, data and UI stay in sync without translation layers.

Browse the showcase to see which states exist before inventing new ones in an API.

Foundations

Color

A beige neutral scale with a green brand primary. Semantic tokens are the API; raw scales are the material they're built from.

Semantic tokens — the styling API31 tokens

Defined in globals.css → :root / .dark. Values resolve through the raw scales — hover a value to see the declaration as written.

basePage canvas & default text

  • --backgroundoklch(0.9512 0.0121 96.4253)
  • --foregroundoklch(0.2435 0 0)

cardElevated surfaces

  • --cardoklch(1 0 0)
  • --card-foregroundoklch(0.2435 0 0)

popoverFloating surfaces

  • --popoveroklch(1 0 0)
  • --popover-foregroundoklch(0.2435 0 0)

primaryBrand green — main actions

  • --primaryoklch(0.5904 0.1251 139.9147)
  • --primary-foregroundoklch(0.9855 0.0174 131.869)

secondaryBrand orange — supporting

  • --secondaryoklch(0.6933 0.2058 42.8784)
  • --secondary-foregroundoklch(0.9846 0.0124 75.3692)

mutedSubdued surfaces & text

  • --mutedoklch(0.9725 0.0067 97.3514)
  • --muted-foregroundoklch(0.5328 0.0463 96.9201)

accentHover & selection

  • --accentoklch(0.9725 0.0067 97.3514)
  • --accent-foregroundoklch(0.359 0.0344 96.3589)

destructiveErrors & irreversible actions

  • --destructiveoklch(0.577 0.245 27.325)

border / input / ringHairlines, fields & focus

  • --borderoklch(0.8657 0.0249 96.6167)
  • --inputoklch(0.8657 0.0249 96.6167)
  • --ringoklch(0.7803 0.0376 96.8081)

chartsData visualization ramp

  • --chart-1oklch(0.7803 0.0589 312.8)
  • --chart-2oklch(0.6254 0.1002 313)
  • --chart-3oklch(0.5062 0.1307 313.4)
  • --chart-4oklch(0.4505 0.142 311.7)
  • --chart-5oklch(0.4004 0.1307 311.3)

sidebarSidebar surfaces & accents

  • --sidebaroklch(0.985 0.0041 91.4457)
  • --sidebar-foregroundoklch(0.2435 0 0)
  • --sidebar-primaryoklch(0.5241 0.107 140.7839)
  • --sidebar-primary-foregroundoklch(0.9855 0.0174 131.869)
  • --sidebar-accentoklch(0.9725 0.0067 97.3514)
  • --sidebar-accent-foregroundoklch(0.359 0.0344 96.3589)
  • --sidebar-borderoklch(0.9512 0.0121 96.4253)
  • --sidebar-ringoklch(0.7803 0.0376 96.8081)

Raw scales — the raw material

greenBrand primary

  • --color-green-50oklch(0.9855 0.0174 131.869)
  • --color-green-100oklch(0.9541 0.0347 129.4029)
  • --color-green-200oklch(0.8959 0.0613 131.4145)
  • --color-green-300oklch(0.811 0.1053 135.5721)
  • --color-green-400oklch(0.6933 0.1222 138.0136)
  • --color-green-500oklch(0.5904 0.1251 139.9147)
  • --color-green-600oklch(0.5241 0.107 140.7839)
  • --color-green-700oklch(0.4581 0.0844 140.6847)
  • --color-green-800oklch(0.3761 0.0672 140.2235)
  • --color-green-900oklch(0.3299 0.0536 141.3419)
  • --color-green-950oklch(0.2233 0.0367 141.7116)

beigeNeutral scale

  • --color-beige-50oklch(0.985 0.0041 91.4457)
  • --color-beige-100oklch(0.9725 0.0067 97.3514)
  • --color-beige-200oklch(0.9512 0.0121 96.4253)
  • --color-beige-300oklch(0.8657 0.0249 96.6167)
  • --color-beige-400oklch(0.7803 0.0376 96.8081)
  • --color-beige-500oklch(0.7036 0.0535 96.335)
  • --color-beige-600oklch(0.6182 0.0499 96.6275)
  • --color-beige-700oklch(0.5328 0.0463 96.9201)
  • --color-beige-800oklch(0.4254 0.0392 98.1981)
  • --color-beige-900oklch(0.359 0.0344 96.3589)
  • --color-beige-950oklch(0.2435 0 0)

orangeBrand secondary

  • --color-orange-50oklch(0.9846 0.0124 75.3692)
  • --color-orange-100oklch(0.957 0.034 77.213)
  • --color-orange-200oklch(0.9009 0.0713 71.648)
  • --color-orange-300oklch(0.8331 0.1223 66.1577)
  • --color-orange-400oklch(0.741 0.1763 53.256)
  • --color-orange-500oklch(0.6933 0.2058 42.8784)
  • --color-orange-600oklch(0.6353 0.2145 37.0344)
  • --color-orange-700oklch(0.5438 0.1884 34.5898)
  • --color-orange-800oklch(0.4622 0.1517 33.6008)
  • --color-orange-900oklch(0.4012 0.1188 34.3827)
  • --color-orange-950oklch(0.2616 0.0763 32.6596)

purpleCharts & data viz

  • --color-purple-50oklch(0.9858 0.0073 312.3)
  • --color-purple-100oklch(0.9433 0.0166 312.6)
  • --color-purple-200oklch(0.883 0.0314 312.7)
  • --color-purple-300oklch(0.7803 0.0589 312.8)
  • --color-purple-400oklch(0.6254 0.1002 313)
  • --color-purple-500oklch(0.5062 0.1307 313.4)
  • --color-purple-600oklch(0.4505 0.142 311.7)
  • --color-purple-700oklch(0.4004 0.1307 311.3)
  • --color-purple-800oklch(0.3536 0.1075 313.2)
  • --color-purple-900oklch(0.3076 0.0868 314.5)
  • --color-purple-950oklch(0.2349 0.0735 312.2)

redErrors & destructive

  • --color-red-50oklch(0.971 0.013 17.38)
  • --color-red-100oklch(0.936 0.032 17.717)
  • --color-red-200oklch(0.885 0.062 18.334)
  • --color-red-300oklch(0.808 0.114 19.571)
  • --color-red-400oklch(0.704 0.191 22.216)
  • --color-red-500oklch(0.637 0.237 25.331)
  • --color-red-600oklch(0.577 0.245 27.325)
  • --color-red-700oklch(0.505 0.213 27.518)
  • --color-red-800oklch(0.444 0.177 26.899)
  • --color-red-900oklch(0.396 0.141 25.723)
  • --color-red-950oklch(0.258 0.092 26.042)

Each scale runs 50 → 950, parsed straight from the tokens in globals.css. Components never reference raw steps directly — they use the semantic tokens above, which remap between light and dark automatically.

Foundations

Typography

Three faces, three jobs — display, body and mono.

--font-heading · GT Alpina CondensedSingle weight: 500

Money that moves with you

Headings and display text. The font ships in one weight only — always pair font-heading with font-medium, never semibold or bold.

--font-sans · Greed Standard

300The quick brown fox jumps over the lazy dog

400The quick brown fox jumps over the lazy dog

500The quick brown fox jumps over the lazy dog

600The quick brown fox jumps over the lazy dog

700The quick brown fox jumps over the lazy dog

Body copy, labels and UI text. Variable font, weights 300–900.

--font-mono · Geist Mono

ACC-2049-8817 · $12,480.00

const balance = formatCurrency(12480)

Code, identifiers and tabular figures — anywhere digits need to line up.

Foundations

Radius, icons & dark mode

The remaining primitives every screen inherits.

Radius

sm

md

lg

xl

2xl

One knob: --radius (0.625rem). Every size derives from it, so changing the knob reshapes the whole system consistently.

Iconography

Phosphor is the only icon library — never lucide. Icons inherit the current text color, so they follow the tokens for free.

Dark mode

Class-based via next-themes — the .dark class remaps every token, so components never branch on theme. Press D to try it.

How the project is structured

A Yarn workspaces + Turborepo monorepo: the design system is a source-shipped package, consumers transpile it.

packages/ui

@workspace/ui — tokens, 60 components, hooks. Source in the monorepo; compiled ESM and types on the release branch.

workspace / release

apps/web

This showcase — every component demoed under the shared tokens.

WestyApp

The product — next consumer, same workspace import.

The public import surface

SubpathWhat it isExample import
./components/*Every component, one module each@workspace/ui/components/button
./hooks/*Shared hooks@workspace/ui/hooks/use-mobile
./lib/*Utilities (cn)@workspace/ui/lib/utils
./globals.cssAll tokens + Tailwind v4 config@workspace/ui/globals.css
./postcss.configThe single PostCSS pipeline@workspace/ui/postcss.config

There is no barrel file — import the exact module you need. The generated release resolves this same surface to compiled files under dist/. Anything not on this surface is internal and may change without notice.

Principles

The five rules that keep the system coherent as it grows.

  1. 01

    Tokens are the styling API

    Components only reference semantic classes — bg-background, text-muted-foreground, border-border. A color that isn't a token doesn't ship.

  2. 02

    Composition over configuration

    Components export families of parts (Field, FieldLabel, FieldDescription…) you compose, instead of piling boolean props onto one component. asChild is the escape hatch for changing the rendered element.

  3. 03

    Native to upstream shadcn/ui

    Components track the upstream output so the CLI can add and update them cleanly. Intent lives in tokens and variants, not hand-edited class strings.

  4. 04

    Every component is demoed

    If it isn't in the showcase, it's invisible and untested. The showcase is the review surface for every change.

  5. 05

    Singletons are owned once

    react, react-dom and next-themes are peer dependencies — the consuming app holds the single copy, so hooks and theme context never split across duplicates.

Component map

All 60 components, grouped into ten categories. Each card jumps to its live demos.

Typography

Type scale, prose and inline text primitives

Buttons

Buttons, button groups and toggles

Forms

Inputs, fields, input groups and validation states

Selection

Checkboxes, radios, selects, sliders and switches

Overlays

Dialogs, sheets, drawers, menus and popovers

Feedback

Alerts, toasts, progress, skeletons and empty states

Data display

Tables, cards, avatars, accordions and badges

Navigation

Tabs, breadcrumbs, pagination, sidebar and menubar

Charts

Recharts primitives themed by the purple ramp

Chat

Messages, bubbles, attachments and scrollers

Westy LLC — built with shadcn/ui, Radix and Tailwind CSS.