# Building UI with the Visualli design system

Read this before writing or refactoring any frontend code in this monorepo (web app, www, MCP apps, Chrome extensions). It is the contract: **build from these components and tokens only.** `CLAUDE.md` in this folder is for changing the design system itself.

## Sources of truth — read in this order

1. `components/dist/index.d.ts` — every component and its props. If it isn't exported here, it isn't in the system.
2. `components/catalog/<Name>/README.md` — when to use each component, and its do's and don'ts.
3. `tokens/tokens.json` — every token, with a `usage` note saying where it belongs. Generated forms: `tokens/dist/tokens.css` (CSS variables), `tokens/dist/tailwind.preset.cjs` (Tailwind), `tokens/dist/tokens.ts` (typed object).
4. `docs/guidelines/brand-book.md` (voice, color roles, type roles), `canvas-language.md` (maps, nodes, gestures), `surfaces.md` (page layouts), `comfort-modes.md` (themes and accessibility).
5. The built docs site (`npm run build` → `docs/dist/`) has a live gallery with copyable JSX for every core component, and `llms.txt` lists every page as Markdown.

## Setup in an app

```ts
import '@visualli/design-system/tokens.css';   // once, at the app root
import '@visualli/design-system/bundle.css';   // once, after tokens.css
import { Button, Card, TextField, Dialog } from '@visualli/design-system/components';
```

Tailwind (3.4) — use the preset so only token values have classes:

```js
// tailwind.config.js — new app
module.exports = { presets: [require('@visualli/design-system/tailwind-preset')], content: ['./src/**/*.{ts,tsx,html}'] };
// existing app while migrating: theme: { extend: require('@visualli/design-system/tailwind-preset').theme }
```

Set the theme on `<html>`: `data-theme` = `light` | `dark` | `focus-light` | `focus-dark` | `colorsafe-light` | `colorsafe-dark` | `contrast-light` | `contrast-dark`, plus `data-type`, `data-motion`, `data-reveal`, `data-scale` — or call `applyComfort(choice)` from `ComfortPanel`. Never branch on dark mode in component code; the variables switch.

## Rules

1. **Components first.** Use a system component whenever one fits. Common names map like this:
   | You want | Use |
   | --- | --- |
   | Button, link button, CTA | `Button` (`variant`: `primary`, `secondary` = outline, `ghost`, `danger`; `size`: `sm`, `md`, `lg`) |
   | Icon-only button | `IconButton` (always pass `label`) |
   | Input, InputField, textarea | `TextField` (`multiline` for textarea) |
   | Search box | `SearchField` |
   | Toggle, checkbox-like setting | `Switch` |
   | Tabs / radio group (2–4 options) | `SegmentedControl` |
   | Modal, dialog, confirm | `Dialog` |
   | Card, tile, panel section | `Card` |
   | Dropdown / context menu | `Menu` |
   | Snackbar, notification | `Toast` |
   | Tag, chip, status pill | `Badge` |
   | Tooltip | `Tooltip` |
   | Icon | `Icon` with a Lucide name from `ICONS` |
   | Loader / spinner | `ThinkingTree` (map work) or `Button loading` |
   | Chat input | `Composer`; messages: `ChatTurn` |
   | Sidebar list of maps | `Vault` / `VaultItem` |
   | Map / mind map / canvas | `VisualMap` (never draw nodes by hand; `Node`, `Edge`, `SemanticPeek`, `DepthTrail` for custom canvases) |
   | Read-only `.visualli` viewer (desktop viewer, third-party embeds) | `VisualliViewer` from `@visualli/design-system/spec` — the spec layer only; never add product features to it |
   | Hover card / summary popover for an idea | `SemanticPeek` |
   | Definition popover for a word, glossary term | `SemanticAnchor` |
   | Explainer side panel / "learn about X" | `GoDeeper` (facets + Map it) |
   | Attachments / uploaded files / "view source" for a map | `SourcesPanel` (via `VisualMap` `aside`) |
   | Chrome extension side panel / "visualize this page" | `ExtensionPanel` (in `chrome.sidePanel`; no own brand or ✕ there) |
   | Floating button group | `.vi-toolbar` with `Button`/`IconButton` (`size="sm"`) |
   | Editing a map: toolbar, contextual actions, inline rename | `VisualMap` `editing`/`onEdit` (renders `EditBanner`, `SelectionBar`, `InlineText`, `SummaryEditor`); `applyEdit` on the server |
   | File / link attachment | `SourceChip` |
   | Settings for theme / accessibility | `ComfortPanel` |
2. **Tokens only for everything else.** Layout and spacing between components use tokens: `var(--space-4)`, `var(--radius-md)`, `var(--surface)` — or the preset's classes (`p-4`, `gap-3`, `rounded-md`, `bg-surface`, `text-ink`, `shadow-float`, `font-ui`, `text-body`). No hex/rgb values, no px values off the spacing scale, no other fonts, no ad-hoc shadows, durations or easings. If a token is missing, stop and ask; don't invent one.
3. **Don't restyle components.** No overriding `vi-*` classes or passing style props to change their look. If a variant is missing, propose it for the design system instead of forking it in the app.
4. **Accessibility is part of done.** Text on the grounds its token note names (4.5:1; 7:1 in `contrast-*`), visible focus (the components handle it; custom elements use `outline: 2px solid var(--focus)`), labels on every control, touch targets ≥ 44px, motion that degrades under `data-motion="reduced"` / `prefers-reduced-motion`. Never encode meaning in color alone.
5. **Brand rules that are easy to break:** no gradients (the spectrum appears as whole adjacent colors: `SpectrumBar`); hand faces (`font-hand`, `font-note`) only on the canvas and in marketing, never in controls; Haksen (`font-display`) is caps-only; one `Signature` word per screen; no colored side borders on cards; no emoji in product chrome.
6. **Copy:** sentence case, American spelling, the vocabulary in the brand book — Visualli / Visuallis, vault, idea (node in code), connector, layer, rings, peek, step inside (enter an idea's layer), go deeper (understand it), map it, bring.
7. **Logos and icons** come from `assets/` and `ICONS`; never redraw, recolor or substitute them.
8. **Check before you finish:** run the app in `light` and `dark` (and one comfort palette), at phone, tablet and desktop widths; no horizontal scroll; no console errors.

## Prompt to give a coding agent

> Build the new **‹page›** using ONLY the components and tokens of our design system. Read `design-system/AGENTS.md` first and follow it: components from `@visualli/design-system/components` (API in `design-system/components/dist/index.d.ts`), every other value from `design-system/tokens/tokens.json` via CSS variables or the Tailwind preset. Don't hard-code colors, sizes, fonts, shadows or motion, and don't restyle components. If something you need doesn't exist, stop and list it as a proposed addition instead of inventing it. Verify in light and dark, and at phone, tablet and desktop widths.
