# Bridge design system > Bridge's design system: the @brdgapp/ui component package (React, Tailwind, Base UI) and its handbook at https://apps-bridge-design-system-handbook.vercel.app. Every Bridge app installs the package and builds screens from its components, tokens, rules, patterns and templates. When code and the handbook disagree, the handbook (and DESIGN.md) wins. ## How to build with it - Install `@brdgapp/ui`; import `@brdgapp/ui/globals.css` once, after `@import "tailwindcss"`. - Import components file by file: `import { Button } from "@brdgapp/ui/components/button"`. There is no single index file. - Use the package's `cn` from `@brdgapp/ui/lib/utils`; never a local copy or plain `clsx`. - Colors only as role tokens: `bg-[var(--surface-secondary)]`, `text-[var(--text-muted)]`. No hex, no palette classes, no `dark:` fixes. - Fills with white text use `--primary-solid` / `--danger-solid`. - A component's look comes from its props (`variant`, `size`); `className` is for layout only. - Links keep their meaning through `render`: ``. - Every data region goes through `DataState` inside its card, with a skeleton the same size as the content. - Cards are glass (`liquid-glass`). Big cards (record, table, settings, centred-card pages; side panels): 16px corners, 24px inside. Tiles (dashboards, feed, public, admin): 12px, 20px inside. 16px apart. Never glass inside glass. - Page title 22px bold + 14px subtitle. Card header: 36px color square + 15px title; a header strip (28px square, 14px title) when the content runs edge to edge. - Text: Mulish on the ladder 11 · 12 · 13 · 14 · 16 · 18 · 22 · 28 (36/48 display). 14px body, 13px for dense rows and tables, 12px meta, nothing below 11px (except the Badge), sentence case. Write the named sizes (`text-13`), not `text-[13px]`: they set the line height too. Text fields are `text-16 md:text-14`. - Spacing: 4px steps; named distances 8 (inside a thing), 12 (related items), 16 (heading to content, between cards), 24 (dialogs), 32 (sections); page edges `px-4 sm:px-6 lg:px-8`. `gap` on the parent, no negative margins, no arbitrary values. - Layout: an app with up to 4 top-level places has a 56px top bar; more than 4, or an admin tool, adds a 240px sidebar under it. Phones: up to 4 places as bottom tabs; a sidebar app opens its places from a menu button. A screen is a page (scrolls with the window) or a tool (fills the screen, panes scroll). Widths from `@brdgapp/ui/lib/layout` (`pageFrame("standard")`). Header: title and one line, actions right (one primary), tabs on records, a toolbar (search left, filters right) over lists. No `w-screen` breakouts or negative margins. - Responsive: phone first; `sm:` 640, `md:` 768, `lg:` 1024, nothing wider. On phones: 44px targets (28px minimum everywhere), bottom sheets for pickers and filters (FilterPill and ColumnFilterMenu switch by themselves), no hover-only actions. `useIsMobile()` only when the structure changes. - Shape: five corners. Round for buttons, search, pills, avatars; 4px tags and badges; 8px fields and icon squares; 12px tiles and menus; 16px big cards and dialogs. Inner corners smaller than outer. Nothing in between. - Elevation: cards are glass (Card); never glass in glass, never a plain white card. Floating components bring their shadow and layer (80 menus/tips/sheets, 90 dialogs, 100 toasts); screens never write a raw shadow or z-index above z-10. - Icons: Lucide only, at its own 2px line (no `strokeWidth`). One icon per meaning: call `find_icon` with the job and use what it returns (Plus add, X close, EllipsisVertical more, Pencil edit, Trash delete, ExternalLink another site, ArrowLeft back, LoaderCircle via `loading`, RefreshCw sync, CircleAlert error, TriangleAlert warning, Sparkles AI). A meaning Bridge doesn't have yet gets an untaken Lucide icon, added to the Iconography table in the same change. Beside words 2px bigger than the text (14 by 12–13px text, 16 by 14px, 18 by 16px); in a square or circle half its width; nothing over 24. Hidden beside words (`aria-hidden`), named when alone (IconButton `aria-label`). Company logos with BrandMark. No emoji in the interface. - Motion: three speeds, 150 (hover, color, press), 200 (menus, sections, toasts), 300 (drawers, sheets, dialogs, entrances), on `ease-out` (the package sets it to Bridge's curve). Animate once; honour reduced motion (`useReducedMotion()` for Framer). ## Always - Call `orient` first, then `plan_screen` for a new screen, then `get_page` for every template, pattern and component you will use. - Import only from `@brdgapp/ui`. If search doesn't return a component for the job, don't invent one: use the closest, or say what's missing. - Start every screen from a template (Picking a template); never invent a new page frame. - Give every data region its loading, empty and error state through DataState. - Write real copy in sentence case: real-sounding people, intros and organizations (the sample network: Ana Ruiz, Leah Okonkwo, Priya Natarajan…). Never Lorem, "Click here", "Submit" or Title Case. - Run `check_code` on what you wrote, fix what it reports, then walk the screen recipe. ## Rules - **One of each** (`one-of-each`): Bridge has one button, one label, one menu, one tooltip, one confirm dialog and one table. Before building a control, look for it here. Never hand-make a second version (a `