@usetheo/ui 0.7.0-next.0 → 0.9.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms.txt ADDED
@@ -0,0 +1,269 @@
1
+ # @usetheo/ui — Theo UI (Violet Forge)
2
+
3
+ > React component library for AI-agent surfaces and cloud (PaaS) dashboards. 114 components (87 primitives + 27 composites), framework-agnostic (React peer-dep only), ESM-only, Apache-2.0. Built on Radix UI + CVA + lucide-react + Tailwind v4. Same Radix foundation as shadcn — the wedge is the agent/PaaS-specific components built on top.
4
+
5
+ This file follows the [llms.txt convention](https://llmstxt.org/) and gives an LLM the **factual ground truth** of the project: package name, import paths, component inventory, locked conventions, anti-patterns, and links to the canonical documentation. Treat the bullets below as non-negotiable contracts unless the source files contradict them — in which case the source files win and this file is stale.
6
+
7
+ ## Project metadata
8
+
9
+ - **npm package:** `@usetheo/ui`
10
+ - **Current version:** `0.8.0-next.0` (npm dist-tag `next`; latest release line)
11
+ - **License:** Apache-2.0
12
+ - **Repository:** `https://github.com/usetheodev/theo-ui`
13
+ - **Docs site:** `https://docs.usetheo.dev/theoui`
14
+ - **Registry (shadcn CLI):** `https://usetheodev.github.io/theo-ui/r/{slug}.json`
15
+ - **Design-system codename:** Violet Forge
16
+ - **Module format:** ESM only (no CJS). `"type": "module"`. Side-effects on `**/*.css`.
17
+ - **React peer range:** `>=18.2.0 <20` (works with 18.x and 19.x)
18
+ - **Distribution:** npm package install OR copy-paste source via shadcn CLI (registry). Both paths are first-class.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ # Full package (recommended for new projects)
24
+ pnpm add @usetheo/ui@next
25
+
26
+ # Per-component copy (shadcn-style)
27
+ npx shadcn@latest add https://usetheodev.github.io/theo-ui/r/copy-button.json
28
+ ```
29
+
30
+ ## Import path canonical form
31
+
32
+ ```ts
33
+ // All components ship via the single barrel.
34
+ import { Button, Table, ConfirmDialog, CopyButton } from "@usetheo/ui";
35
+
36
+ // Themes + provider:
37
+ import { ThemeProvider, violetForge, classicPaper, auroraTerminal } from "@usetheo/ui";
38
+
39
+ // Pure utility (no React):
40
+ import { cn } from "@usetheo/ui";
41
+
42
+ // Engines ship under subpaths (separate bundles, opt-in peer-deps):
43
+ import { Whiteboard } from "@usetheo/ui/whiteboard";
44
+ import { Slide } from "@usetheo/ui/slide";
45
+ import { SlideDeck } from "@usetheo/ui/slide-deck";
46
+ import { Mermaid } from "@usetheo/ui/slide/plugins/mermaid";
47
+ import { Math } from "@usetheo/ui/slide/plugins/math";
48
+ import { Shiki } from "@usetheo/ui/slide/plugins/shiki";
49
+ import { Emoji } from "@usetheo/ui/slide/plugins/emoji";
50
+ import { theoUIVitePlugin } from "@usetheo/ui/vite-plugin";
51
+ import "@usetheo/ui/preset"; // Tailwind v4 preset (zero-config)
52
+ ```
53
+
54
+ There are **131 subpath exports** in `package.json#exports` — one per component plus engine entry points. Per-component subpath imports (`@usetheo/ui/button`) exist but are **not the canonical form**; prefer the barrel for tree-shakeable production builds (`sideEffects: ["**/*.css"]` is honored).
55
+
56
+ ## Peer dependencies (required vs optional)
57
+
58
+ **Required for the main barrel:**
59
+ - `react >=18.2.0 <20`
60
+ - `react-dom >=18.2.0 <20`
61
+ - `tailwindcss ^4.0.0`
62
+
63
+ **Optional (only required if you use the matching engine subpath):**
64
+ - `@tailwindcss/vite ^4.0.0`, `vite ^6 || ^7` — for `@usetheo/ui/vite-plugin`
65
+ - `roughjs ^4.6`, `perfect-freehand ^1.2` — for `@usetheo/ui/whiteboard`
66
+ - `mdast-util-from-markdown`, `mdast-util-gfm`, `mdast-util-to-hast`, `hast-util-sanitize`, `hast-util-to-jsx-runtime`, `micromark-extension-gfm`, `unist-util-visit`, `unist-util-visit-parents`, `yaml` — for `@usetheo/ui/slide`
67
+ - `shiki ^1.0` — for `@usetheo/ui/slide/plugins/shiki`
68
+ - `katex ^0.16`, `mdast-util-math`, `micromark-extension-math` — for `@usetheo/ui/slide/plugins/math`
69
+ - `mermaid ^11.0` — for `@usetheo/ui/slide/plugins/mermaid`
70
+ - `hast-util-from-html` — for `@usetheo/ui/slide/plugins/emoji`
71
+
72
+ **Already bundled (do NOT install separately):** `@radix-ui/*`, `class-variance-authority`, `clsx`, `cmdk`, `lucide-react`, `tailwind-merge`. These are `dependencies`, not peer.
73
+
74
+ ## Taxonomy (mechanical rule, gate-enforced)
75
+
76
+ - **Primitive** = a component that imports **zero** other `@usetheo/ui` components. Lives in `src/components/primitives/`.
77
+ - **Composite** = a component that imports **one or more** primitives via their barrel `index.js`. Lives in `src/components/composites/`.
78
+ - The gate `scripts/validate-quality-gates.ts` is **hard-fail** if either rule is violated. A primitive that grows to need a sibling primitive must be **promoted to composite** by moving the folder + renaming via PR with rationale.
79
+ - Composites import siblings via barrel: `import { Button } from "../../primitives/button/index.js"` — NOT via the raw `.tsx` file (also gate-enforced).
80
+ - Sub-component pattern (e.g., `Table.Header`, `Sidebar.Item`, `DangerZone.Action`) is implemented via `Object.assign(Root, { SubA, SubB })` — Sidebar-style. Single import surface, attached as static properties on the root.
81
+
82
+ ## Theme system
83
+
84
+ - **Provider:** `<ThemeProvider initial="violet-forge">{...}</ThemeProvider>`. Wrap once at the app root.
85
+ - **Built-in themes (10):** `violetForge` (default), `classicPaper`, `auroraTerminal`, `vercelMono`, `githubDark`, `dracula`, `oneDark`, `anthropicStyle`, `openaiStyle`, `linearGlass`.
86
+ - **Custom themes:** `defineTheme({ name, mode, fonts, palette })` — returns a `Theme` object you pass into `<ThemeProvider extra={[myTheme]} />`.
87
+ - **Color helpers:** `hex("#7c5cff")`, `rgb(124, 92, 255)` — both return CSS-ready strings.
88
+ - **Density:** `useDensity()` hook returns `"compact" | "comfortable" | "cozy"`. Cascading via `<DensityProvider>`.
89
+ - **Fonts (locked):** Geist Sans (display + body) + Geist Mono (mono). Loaded via CDN by default (`dist/fonts-cdn.css`) or locally (`dist/fonts.css`).
90
+ - **Tailwind v4:** CSS-first config via `@usetheo/ui/preset` (zero JS config). v3 legacy preset available at `@usetheo/ui/preset-v3-legacy`.
91
+
92
+ ## Component catalog — primitives (87)
93
+
94
+ Located in `src/components/primitives/{slug}/`. Each ships `.tsx` + `.test.tsx` + `.stories.tsx` + `index.ts` + a `registry/{slug}.json` descriptor.
95
+
96
+ `agent-error-card`, `agent-event`, `agent-handoff`, `agent-profile`, `agent-starting-state`, `agent-streaming`, `artifact-preview`, `attachment-chip`, `audit-log-entry`, `auto-compact-notice`, `avatar`, `badge`, `browser-controls`, `build-log-stream`, `button`, `capability-indicator`, `card`, `chat-thread`, `checkbox`, `context-card`, `context-window-bar`, **`copy-button`** (NEW 0.8), `cost-meter`, `created-files-card`, `cron-job-card`, **`danger-zone`** (NEW 0.8), `dialog`, `diff-viewer`, `empty-state`, `folder-context-card`, `folder-selector`, `form-field`, `hook-config`, `hook-event-log`, `input`, `intent-selector`, `label`, `lane-board`, `login-split`, `mcp-server-card`, `memory-editor`, `mention-menu`, `metrics-panel`, `model-card`, `model-selector`, `permission-matrix`, **`plan-badge`** (0.7), **`progress`** (0.7), `progress-checklist`, `project-switcher`, `quick-action-chips`, `radio-group`, `recent-folders-list`, `rule-card`, `running-tasks-panel`, `run-stats`, `scroll-area`, `select`, `session-list-item`, `session-timeline`, `sheet`, `sidebar`, `skeleton`, `skill-card`, `slide`, `social-auth-row`, **`stat-tile`** (NEW 0.8), **`status-dot`** (NEW 0.8), `steps-rail`, `sub-agent-dispatch`, `switch`, `system-prompt-editor`, **`table`** (NEW 0.8), `tabs`, `task-plan`, `terminal-panel`, `textarea`, **`timestamp`** (NEW 0.8), `toast`, `token-usage-chart`, `tool-call`, `tool-call-card`, `tool-result`, `tools-list`, `tooltip`, `topnav`, `whiteboard`.
97
+
98
+ ## Component catalog — composites (27)
99
+
100
+ Located in `src/components/composites/{slug}/`.
101
+
102
+ **`account-menu`** (0.7), `agent-composer`, `agent-editor`, `agent-stream`, `agent-timeline`, `approval-card`, `chat-composer`, `chat-message`, **`code-block`** (NEW 0.8), `command-palette`, **`confirm-dialog`** (NEW 0.8), `cron-jobs-list`, `deployment-row`, `domain-config`, `env-var-editor`, `mcp-server-list`, `permission-modal`, `preview-env-card`, `preview-panel`, `project-card`, `rollback-ui`, `rule-editor`, `skill-editor`, `skills-list`, `slide-deck`, `task-header`, **`usage-meter`** (0.7).
103
+
104
+ ## Recent deliveries (PaaS shape)
105
+
106
+ - **0.8.0-next.0 (Brief #2 — cross-cutting, 8 components):** `Table` (sub-components + sortable headers), `StatusDot` (5 kinds + auto-pulse), `CopyButton` (clipboard + `aria-live` + SSR-safe), `Timestamp` (`Intl.RelativeTimeFormat`, native `title` tooltip, Unix ms only), `StatTile` (dual button/div mode), `DangerZone` (`.Action` sub-component), `ConfirmDialog` (typed-phrase guard + async loading + Enter-to-confirm), `CodeBlock` (terminal prefix + caption + raw-code copy). Consumer: TheoCloud dashboard. Zero new peer-deps; bundle +5.4% (rebaselined).
107
+ - **0.7.0-next.0 (Brief #1 — PaaS-shape, 4 components):** `UsageMeter` (multi-metric, over-quota warning + clamping), `Progress` (4 intents + indeterminate + motion-reduce aware), `PlanBadge` (5 canonical tiers), `AccountMenu` (avatar + name + plan + secondary, dual button/div).
108
+
109
+ ## Component conventions (do this)
110
+
111
+ Every component file MUST:
112
+
113
+ 1. Use `forwardRef<HTMLElementType, Props>` and set `displayName`. Example: `MyComponent.displayName = "MyComponent";`.
114
+ 2. Compose classes via `cn(...)` from `lib/cn.js` (`tailwind-merge` + `clsx` underneath).
115
+ 3. Use **design tokens** only — never raw hex/rgb. Approved tokens: `bg-card`, `bg-muted`, `bg-muted/40`, `bg-primary`, `bg-primary/10`, `bg-success`, `bg-warning`, `bg-destructive`, `bg-destructive/[0.02]`, `text-foreground`, `text-muted-foreground`, `text-success`, `text-warning`, `text-destructive`, `border-border/40`, `border-border/60`, `border-destructive/30`, `text-card-foreground`, `text-primary-foreground`, `ring-ring`, etc.
116
+ 4. Use **typography scale**: `text-display-md`, `text-title-sm`, `text-body-sm`, `text-label`, `text-label-caps`, `font-display`, `font-sans`, `font-mono` — never raw `text-xl`/`text-base`/`text-sm`.
117
+ 5. Use `lucide-react` for icons. Never inline SVG. Icons rendered as components (`<Copy aria-hidden="true" className="size-3.5" />`).
118
+ 6. Use CVA (`class-variance-authority`) for variant APIs that have ≥3 options (Button, Badge, Progress intent, etc.).
119
+ 7. Pass `aria-label` for icon-only triggers. Use `<span className="sr-only" aria-live="polite">` for state announcements (CopyButton pattern).
120
+ 8. Tests use `vitest` + `@testing-library/react` + `vitest-axe`. Every interactive primitive ships `expect(await axe(container)).toHaveNoViolations()`. Async assertions use `findBy*` with `{ timeout: 5000 }` headroom for parallel vitest pool.
121
+ 9. Stories ship in Ladle (`.stories.tsx`). Title pattern: `"Primitives / {Category} / {Name}"` or `"Composites / {Category} / {Name}"`.
122
+ 10. Registry descriptor in `registry/{slug}.json` with shadcn schema. Each entry declares `dependencies` (npm) + `registryDependencies` (other registry items in this project).
123
+
124
+ ## Anti-patterns (do NOT)
125
+
126
+ - **Do NOT** add raw hex/rgb. Always use tokens. The design-audit gate fails the build if it finds them.
127
+ - **Do NOT** install Radix / CVA / lucide-react separately — they're bundled `dependencies`.
128
+ - **Do NOT** import a sibling primitive into another primitive (taxonomy gate hard-fails). Either inline the dep or promote to composite.
129
+ - **Do NOT** import via `../../primitives/foo/foo.js` from a composite — use `../../primitives/foo/index.js` (gate hard-fails).
130
+ - **Do NOT** wrap dropdown/dialog/select in your own Portal. Radix manages portals correctly.
131
+ - **Do NOT** disable a quality gate or add `eslint-disable`/`biome-ignore` to silence one — fix the root cause. Acceptable biome-ignore comments must include a `WAI-ARIA …` or equivalent justification.
132
+ - **Do NOT** roll your own clipboard, focus-trap, accessible dialog, color parser, markdown renderer, syntax highlighter, or relative-time formatter — use `<CopyButton>`, Radix Dialog, `Intl.RelativeTimeFormat`, etc.
133
+ - **Do NOT** ship CJS (`require()`). ESM only. The TypeScript output is `.js` with `.d.ts` siblings.
134
+ - **Do NOT** rename the locked names (see below) without a strategic review.
135
+ - **Do NOT** use emojis in code, README, JSDoc, or CHANGELOG. (User-facing copy in docs is OK if explicitly requested.)
136
+ - **Do NOT** invent integration that doesn't exist. As of 2026-05-23, `@usetheo/ui` has **no** import from `@usetheo/sdk`, `theokit`, or `theo-code`. Verify with `grep` before claiming wiring.
137
+
138
+ ## Locked names (immutable without strategic review)
139
+
140
+ | Item | Value |
141
+ |---|---|
142
+ | npm package | `@usetheo/ui` |
143
+ | Codename | Violet Forge |
144
+ | Default theme | `violet-forge` |
145
+ | Built-in themes (3 originals) | `violet-forge`, `classic-paper`, `aurora-terminal` |
146
+ | ThemeProvider component | `<ThemeProvider />` |
147
+ | Registry endpoint (planned canonical) | `ui.usetheo.dev/r/*.json` |
148
+ | Module format | ESM only |
149
+ | Quality-gate command | `pnpm quality:gates` |
150
+ | Test framework | Vitest |
151
+ | Stories framework | Ladle |
152
+ | Linter / formatter | Biome (`biome check`, `biome format`) |
153
+ | Component taxonomy | `primitive` (no internal deps) vs `composite` (≥1 internal dep) |
154
+ | Fonts | Geist Sans + Geist Mono (CDN by default) |
155
+
156
+ ## Engines (subpath-isolated, opt-in)
157
+
158
+ These ship under their own subpath because they require heavy peer-deps. **Do NOT** include in the main barrel.
159
+
160
+ | Engine | Subpath | Required peer-deps |
161
+ |---|---|---|
162
+ | Whiteboard (Excalidraw-style view) | `@usetheo/ui/whiteboard` | `roughjs`, `perfect-freehand` |
163
+ | Slide (Marp-style view) | `@usetheo/ui/slide` | `mdast-util-*`, `hast-util-*`, `micromark-extension-gfm`, `unist-util-visit*`, `yaml` |
164
+ | SlideDeck | `@usetheo/ui/slide-deck` | inherits from Slide |
165
+ | Slide plugin — Shiki | `@usetheo/ui/slide/plugins/shiki` | `shiki` |
166
+ | Slide plugin — Math (KaTeX) | `@usetheo/ui/slide/plugins/math` | `katex`, `mdast-util-math`, `micromark-extension-math` |
167
+ | Slide plugin — Mermaid | `@usetheo/ui/slide/plugins/mermaid` | `mermaid` |
168
+ | Slide plugin — Emoji | `@usetheo/ui/slide/plugins/emoji` | `hast-util-from-html` |
169
+ | Vite plugin | `@usetheo/ui/vite-plugin` | `vite ^6 || ^7`, `@tailwindcss/vite` |
170
+
171
+ All engines documented under RFC 0001 / 0002 / 0003 / 0004 in `docs/rfcs/`. View-only (no editing) by design.
172
+
173
+ ## Quality gates (run via `pnpm quality:gates`)
174
+
175
+ The full chain runs in CI and must be 100% green for any PR to merge:
176
+
177
+ 1. `format:check` — Biome formatter
178
+ 2. `lint:ci` — Biome linter (strict)
179
+ 3. `typecheck` — `tsc --noEmit` (strict TS)
180
+ 4. `test` — Vitest run (1532+ tests including `vitest-axe` a11y)
181
+ 5. `build` — tsup (ESM + d.ts + CSS)
182
+ 6. `registry:build` + `registry:validate` — shadcn descriptors
183
+ 7. `quality:structure` — taxonomy + readme drift + design-audit + test/story coverage
184
+ 8. `quality:bundle` — `dist/index.js` size delta within ±5% baseline (rebaseline explicit via `--update`)
185
+ 9. `quality:a11y` — every interactive Ladle story axe-validated (~226 tests)
186
+ 10. `ladle:build` — verify Ladle compiles
187
+ 11. `dogfood:*` — end-to-end smoke against each engine
188
+
189
+ ## Test conventions
190
+
191
+ - Framework: **Vitest** (NOT Jest). Use `vi.fn()`, `vi.spyOn()`, `vi.useFakeTimers()`.
192
+ - Renderer: `@testing-library/react`. Always `render(<C ... />)`, never manual `ReactDOM.render`.
193
+ - A11y: `import { axe } from "vitest-axe"; expect(await axe(container)).toHaveNoViolations();`
194
+ - Async assertions: `await screen.findByText(...)` (not `getByText` then `waitFor`). For tests under parallel vitest pool stress, add `{ timeout: 5000 }`.
195
+ - Radix dialog tests: use `baseElement` (not `container`) for portal-rendered content. Disable `aria-hidden-focus` rule on axe runs over Dialog content — it's a false positive on Radix's focus-guard spans.
196
+ - Clipboard tests: `vi.stubGlobal("navigator", { clipboard: { writeText: vi.fn() } });`.
197
+ - Time/Date tests: `vi.useFakeTimers(); vi.setSystemTime(new Date("2026-05-23T12:00:00Z"));`.
198
+
199
+ ## Stories convention (Ladle)
200
+
201
+ ```tsx
202
+ import type { Story } from "@ladle/react";
203
+ import { MyComponent } from "./my-component.js";
204
+
205
+ export default { title: "Primitives / Category / MyComponent" };
206
+
207
+ export const Default: Story = () => <MyComponent prop="value" />;
208
+ ```
209
+
210
+ Run dev server: `pnpm dev` (Ladle on `http://localhost:61000`). Build static: `pnpm ladle:build`. Title pattern is enforced for sidebar grouping.
211
+
212
+ ## Documentation URLs (canonical)
213
+
214
+ - **Site:** `https://docs.usetheo.dev/theoui`
215
+ - **Per-component MDX pages (curated, not auto-gen):**
216
+ - Primitives: `https://docs.usetheo.dev/theoui/primitives/{slug}`
217
+ - Composites: most live under their domain dir — `infra/`, `code/`, `agent/`, `auth/`, `tools/`, `models/`, `tasks/`. Examples:
218
+ - `https://docs.usetheo.dev/theoui/infra/account-menu` (PaaS surface)
219
+ - `https://docs.usetheo.dev/theoui/infra/usage-meter`
220
+ - `https://docs.usetheo.dev/theoui/code/code-block`
221
+ - `https://docs.usetheo.dev/theoui/primitives/table`
222
+ - `https://docs.usetheo.dev/theoui/primitives/confirm-dialog`
223
+ - **Theming guide:** `https://docs.usetheo.dev/theoui/theming`
224
+ - **Engines:** `https://docs.usetheo.dev/theoui/engines/{whiteboard,slide,slide-deck}`
225
+ - **CHANGELOG:** `https://github.com/usetheodev/theo-ui/blob/main/CHANGELOG.md`
226
+
227
+ ## Source-of-truth files (read these before claiming anything)
228
+
229
+ 1. `/CLAUDE.md` — project contract (locked names, taxonomy gate, voice/tone scope, inviolable rules)
230
+ 2. `/README.md` — public catalog + quality gates + dev scripts (auto-synced from filesystem by `pnpm sync:readme`)
231
+ 3. `/CHANGELOG.md` — every release entry, including [Unreleased] section
232
+ 4. `/package.json#exports` — the authoritative list of subpath imports (auto-synced by `pnpm sync:exports`)
233
+ 5. `/src/index.ts` — the barrel; every public component appears here
234
+ 6. `/docs/architecture.md` — folder layout + module boundaries
235
+ 7. `/docs/design-system.md` — tokens, fonts, type scale (Geist + Vercel scale, locked)
236
+ 8. `/docs/rfcs/*.md` — engine RFCs (whiteboard 0001, slide 0002, slide-deck 0003, slide-rich-content 0004, themes 0007, integration 0008, chat-message 0009)
237
+ 9. `/scripts/validate-quality-gates.ts` — the taxonomy + structure gate
238
+ 10. `/.claude/knowledge-base/plans/*.md` — every change of ≥3 phases has a written plan; the most recent is `dashboard-paas-primitives-2-plan.md` (Brief #2)
239
+
240
+ ## How to add a new component (the rote checklist)
241
+
242
+ 1. Decide taxonomy: does it import another `@usetheo/ui` component? If yes → composite. If no → primitive.
243
+ 2. Create folder: `src/components/{primitives,composites}/{kebab-name}/`
244
+ 3. Create 4 files: `{slug}.tsx`, `{slug}.test.tsx`, `{slug}.stories.tsx`, `index.ts`
245
+ 4. Implement with `forwardRef` + `displayName` + `cn()` + lucide icons + design tokens + typography scale
246
+ 5. Tests: ≥6 unit tests including 1 `vitest-axe` assertion
247
+ 6. Stories: ≥3 Ladle stories (variants/sizes/states)
248
+ 7. Add registry descriptor: `registry/{slug}.json` with `$schema`, `name`, `type: "registry:ui"`, `title`, `description`, `dependencies`, `registryDependencies`, `files`
249
+ 8. Add export to `src/index.ts` (the barrel)
250
+ 9. Run `pnpm sync:exports && pnpm sync:readme` to regenerate `package.json#exports` + README + architecture catalog + Ladle stats
251
+ 10. Add CHANGELOG entry under `## [Unreleased]` → `### Added` with one bullet per component
252
+ 11. Run `pnpm quality:gates` — must be 100% green
253
+ 12. If shipping to consumers, also write a curated MDX page in `theo-opendocs` (NEVER use auto-gen `/components/` dir — that's broken legacy)
254
+
255
+ ## Cross-project positioning
256
+
257
+ `@usetheo/ui` is the **UI pillar** of the `usetheo` ecosystem. Other pillars:
258
+
259
+ - **Harness** — `@usetheo/sdk` (Claude Agent SDK consumer). No current import from `@usetheo/ui`.
260
+ - **Skills** — `theokit` (agent framework). No current import.
261
+ - **Runtime** — Theo PaaS (cloud platform, pre-release). No current import; `<DeploymentRow>`, `<BuildLogStream>`, `<RollbackUI>`, `<EnvVarEditor>`, `<DomainConfig>`, `<PreviewEnvCard>`, `<ProjectCard>`, `<MetricsPanel>`, and the new Brief #1 + #2 components are designed for it but currently unused.
262
+
263
+ `@usetheo/ui` is **community auxiliary**: Apache-2.0, usable standalone, no commitment to the rest of the stack. The integration story above is aspirational; verify with `grep` before claiming wiring exists in any consumer.
264
+
265
+ ## When this file is stale
266
+
267
+ The code, the README, and the `package.json#exports` map are **authoritative**. If `llms.txt` disagrees with them, the code wins — update this file via PR with a one-line rationale. Locked names (Section "Locked names") and voice/narrative rules require a strategic review at the monorepo level before being weakened or repealed.
268
+
269
+ — Generated 2026-05-23 from filesystem inventory + `CLAUDE.md` + `README.md`. Regenerate by inspecting `src/components/{primitives,composites}/*/` directories and updating the catalog sections above.
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@usetheo/ui",
3
- "version": "0.7.0-next.0",
3
+ "version": "0.9.0-next.0",
4
4
  "description": "Theo UI — framework-agnostic React component library with the Violet Forge design system. Focused on AI-agent interfaces, cloud dashboards, and developer-tooling surfaces.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
- "sideEffects": ["**/*.css"],
7
+ "sideEffects": [
8
+ "**/*.css"
9
+ ],
8
10
  "exports": {
9
11
  ".": {
10
12
  "types": "./dist/index.d.ts",
@@ -65,6 +67,10 @@
65
67
  "types": "./dist/index.d.ts",
66
68
  "import": "./dist/index.js"
67
69
  },
70
+ "./alert": {
71
+ "types": "./dist/index.d.ts",
72
+ "import": "./dist/index.js"
73
+ },
68
74
  "./approval-card": {
69
75
  "types": "./dist/index.d.ts",
70
76
  "import": "./dist/index.js"
@@ -129,10 +135,18 @@
129
135
  "types": "./dist/index.d.ts",
130
136
  "import": "./dist/index.js"
131
137
  },
138
+ "./code-block": {
139
+ "types": "./dist/index.d.ts",
140
+ "import": "./dist/index.js"
141
+ },
132
142
  "./command-palette": {
133
143
  "types": "./dist/index.d.ts",
134
144
  "import": "./dist/index.js"
135
145
  },
146
+ "./confirm-dialog": {
147
+ "types": "./dist/index.d.ts",
148
+ "import": "./dist/index.js"
149
+ },
136
150
  "./context-card": {
137
151
  "types": "./dist/index.d.ts",
138
152
  "import": "./dist/index.js"
@@ -141,6 +155,10 @@
141
155
  "types": "./dist/index.d.ts",
142
156
  "import": "./dist/index.js"
143
157
  },
158
+ "./copy-button": {
159
+ "types": "./dist/index.d.ts",
160
+ "import": "./dist/index.js"
161
+ },
144
162
  "./cost-meter": {
145
163
  "types": "./dist/index.d.ts",
146
164
  "import": "./dist/index.js"
@@ -157,6 +175,10 @@
157
175
  "types": "./dist/index.d.ts",
158
176
  "import": "./dist/index.js"
159
177
  },
178
+ "./danger-zone": {
179
+ "types": "./dist/index.d.ts",
180
+ "import": "./dist/index.js"
181
+ },
160
182
  "./deployment-row": {
161
183
  "types": "./dist/index.d.ts",
162
184
  "import": "./dist/index.js"
@@ -249,6 +271,10 @@
249
271
  "types": "./dist/index.d.ts",
250
272
  "import": "./dist/index.js"
251
273
  },
274
+ "./pagination": {
275
+ "types": "./dist/index.d.ts",
276
+ "import": "./dist/index.js"
277
+ },
252
278
  "./permission-matrix": {
253
279
  "types": "./dist/index.d.ts",
254
280
  "import": "./dist/index.js"
@@ -361,6 +387,14 @@
361
387
  "types": "./dist/index.d.ts",
362
388
  "import": "./dist/index.js"
363
389
  },
390
+ "./stat-tile": {
391
+ "types": "./dist/index.d.ts",
392
+ "import": "./dist/index.js"
393
+ },
394
+ "./status-dot": {
395
+ "types": "./dist/index.d.ts",
396
+ "import": "./dist/index.js"
397
+ },
364
398
  "./steps-rail": {
365
399
  "types": "./dist/index.d.ts",
366
400
  "import": "./dist/index.js"
@@ -377,6 +411,10 @@
377
411
  "types": "./dist/index.d.ts",
378
412
  "import": "./dist/index.js"
379
413
  },
414
+ "./table": {
415
+ "types": "./dist/index.d.ts",
416
+ "import": "./dist/index.js"
417
+ },
380
418
  "./tabs": {
381
419
  "types": "./dist/index.d.ts",
382
420
  "import": "./dist/index.js"
@@ -397,6 +435,10 @@
397
435
  "types": "./dist/index.d.ts",
398
436
  "import": "./dist/index.js"
399
437
  },
438
+ "./timestamp": {
439
+ "types": "./dist/index.d.ts",
440
+ "import": "./dist/index.js"
441
+ },
400
442
  "./toast": {
401
443
  "types": "./dist/index.d.ts",
402
444
  "import": "./dist/index.js"
@@ -470,44 +512,15 @@
470
512
  "import": "./dist/preset-v3-legacy.js"
471
513
  }
472
514
  },
473
- "files": ["dist", "registry/r", "registry/index.json", "LICENSE", "NOTICE", "CHANGELOG.md"],
474
- "scripts": {
475
- "build": "tsup",
476
- "dev": "ladle serve",
477
- "ladle:build": "ladle build",
478
- "ladle:preview": "ladle preview",
479
- "playground": "vite --config playground/vite.config.ts",
480
- "playground:build": "vite build --config playground/vite.config.ts",
481
- "playground:preview": "vite preview --config playground/vite.config.ts",
482
- "typecheck": "tsc --noEmit",
483
- "lint": "biome check src",
484
- "lint:ci": "biome ci src scripts .ladle playground",
485
- "lint:fix": "biome check --write src",
486
- "format": "biome format --write src scripts .ladle package.json tsconfig.json tailwind.config.ts vitest.config.ts tsup.config.ts biome.json",
487
- "format:check": "biome format src scripts .ladle package.json tsconfig.json tailwind.config.ts vitest.config.ts tsup.config.ts biome.json",
488
- "test": "vitest run",
489
- "test:watch": "vitest",
490
- "test:ui": "vitest --ui",
491
- "registry:build": "tsx scripts/build-registry.ts",
492
- "registry:validate": "tsx scripts/validate-registry.ts",
493
- "sync:readme": "tsx scripts/sync-readme.ts",
494
- "sync:exports": "tsx scripts/sync-exports.ts",
495
- "test:registry": "tsx scripts/test-registry-install.ts",
496
- "test:coverage": "vitest run --coverage",
497
- "quality:structure": "tsx scripts/validate-quality-gates.ts",
498
- "quality:bundle": "tsx scripts/validate-bundle-size.ts",
499
- "quality:bundle:update": "tsx scripts/validate-bundle-size.ts --update",
500
- "quality:a11y": "vitest run src/test/ladle-axe.test.tsx",
501
- "dogfood:whiteboard": "tsx scripts/dogfood-whiteboard.ts",
502
- "dogfood:slide": "tsx scripts/dogfood-slide.ts",
503
- "dogfood:slide-deck": "tsx scripts/dogfood-slide-deck.ts",
504
- "dogfood:slide-rich": "tsx scripts/dogfood-slide-rich.ts",
505
- "dogfood:v4-zero-config": "tsx scripts/dogfood-v4-zero-config.ts",
506
- "dogfood:v4-real-build": "bash scripts/dogfood-v4-real-build.sh",
507
- "dogfood:precompiled-utilities": "tsx scripts/dogfood-precompiled-utilities.ts",
508
- "quality:gates": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm test && pnpm build && pnpm registry:build && pnpm registry:validate && pnpm quality:structure && pnpm quality:bundle && pnpm quality:a11y && pnpm ladle:build && pnpm dogfood:whiteboard && pnpm dogfood:slide && pnpm dogfood:slide-deck && pnpm dogfood:slide-rich && pnpm dogfood:v4-zero-config && pnpm dogfood:precompiled-utilities",
509
- "quality:gates:fast": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm registry:build && pnpm registry:validate && pnpm quality:structure"
510
- },
515
+ "files": [
516
+ "dist",
517
+ "registry/r",
518
+ "registry/index.json",
519
+ "LICENSE",
520
+ "NOTICE",
521
+ "CHANGELOG.md",
522
+ "llms.txt"
523
+ ],
511
524
  "peerDependencies": {
512
525
  "@tailwindcss/vite": "^4.0.0",
513
526
  "hast-util-from-html": "^2.0.0",
@@ -660,12 +673,6 @@
660
673
  "engines": {
661
674
  "node": ">=20"
662
675
  },
663
- "pnpm": {
664
- "onlyBuiltDependencies": ["@biomejs/biome", "@swc/core", "esbuild"],
665
- "overrides": {
666
- "postcss": ">=8.5.10"
667
- }
668
- },
669
676
  "keywords": [
670
677
  "react",
671
678
  "components",
@@ -681,5 +688,41 @@
681
688
  "publishConfig": {
682
689
  "access": "public"
683
690
  },
684
- "packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be"
685
- }
691
+ "scripts": {
692
+ "build": "tsup",
693
+ "dev": "ladle serve",
694
+ "ladle:build": "ladle build",
695
+ "ladle:preview": "ladle preview",
696
+ "playground": "vite --config playground/vite.config.ts",
697
+ "playground:build": "vite build --config playground/vite.config.ts",
698
+ "playground:preview": "vite preview --config playground/vite.config.ts",
699
+ "typecheck": "tsc --noEmit",
700
+ "lint": "biome check src",
701
+ "lint:ci": "biome ci src scripts .ladle playground",
702
+ "lint:fix": "biome check --write src",
703
+ "format": "biome format --write src scripts .ladle package.json tsconfig.json tailwind.config.ts vitest.config.ts tsup.config.ts biome.json",
704
+ "format:check": "biome format src scripts .ladle package.json tsconfig.json tailwind.config.ts vitest.config.ts tsup.config.ts biome.json",
705
+ "test": "vitest run",
706
+ "test:watch": "vitest",
707
+ "test:ui": "vitest --ui",
708
+ "registry:build": "tsx scripts/build-registry.ts",
709
+ "registry:validate": "tsx scripts/validate-registry.ts",
710
+ "sync:readme": "tsx scripts/sync-readme.ts",
711
+ "sync:exports": "tsx scripts/sync-exports.ts",
712
+ "test:registry": "tsx scripts/test-registry-install.ts",
713
+ "test:coverage": "vitest run --coverage",
714
+ "quality:structure": "tsx scripts/validate-quality-gates.ts",
715
+ "quality:bundle": "tsx scripts/validate-bundle-size.ts",
716
+ "quality:bundle:update": "tsx scripts/validate-bundle-size.ts --update",
717
+ "quality:a11y": "vitest run src/test/ladle-axe.test.tsx",
718
+ "dogfood:whiteboard": "tsx scripts/dogfood-whiteboard.ts",
719
+ "dogfood:slide": "tsx scripts/dogfood-slide.ts",
720
+ "dogfood:slide-deck": "tsx scripts/dogfood-slide-deck.ts",
721
+ "dogfood:slide-rich": "tsx scripts/dogfood-slide-rich.ts",
722
+ "dogfood:v4-zero-config": "tsx scripts/dogfood-v4-zero-config.ts",
723
+ "dogfood:v4-real-build": "bash scripts/dogfood-v4-real-build.sh",
724
+ "dogfood:precompiled-utilities": "tsx scripts/dogfood-precompiled-utilities.ts",
725
+ "quality:gates": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm test && pnpm build && pnpm registry:build && pnpm registry:validate && pnpm quality:structure && pnpm quality:bundle && pnpm quality:a11y && pnpm ladle:build && pnpm dogfood:whiteboard && pnpm dogfood:slide && pnpm dogfood:slide-deck && pnpm dogfood:slide-rich && pnpm dogfood:v4-zero-config && pnpm dogfood:precompiled-utilities",
726
+ "quality:gates:fast": "pnpm format:check && pnpm lint:ci && pnpm typecheck && pnpm registry:build && pnpm registry:validate && pnpm quality:structure"
727
+ }
728
+ }
@@ -16,7 +16,7 @@
16
16
  "name": "account-menu",
17
17
  "type": "registry:ui",
18
18
  "title": "AccountMenu",
19
- "description": "Sidebar header for PaaS surfaces. Avatar + name + (optional) PlanBadge + (optional) secondary line, with dual mode: with onClick renders as a <button> with trailing chevron (account picker affordance); without, renders as a static <div>. PaaS-shape sibling of ProjectSwitcher."
19
+ "description": "Sidebar header for PaaS surfaces. Avatar + name + (optional) PlanBadge + (optional) secondary line, with dual mode: with onClick renders as a `button` with trailing chevron (account picker affordance); without, renders as a static `div`. PaaS-shape sibling of ProjectSwitcher."
20
20
  },
21
21
  {
22
22
  "name": "agent-composer",
@@ -84,6 +84,12 @@
84
84
  "title": "Theo UI agent types",
85
85
  "description": "Shared TypeScript types for the agent timeline, events, and statuses."
86
86
  },
87
+ {
88
+ "name": "alert",
89
+ "type": "registry:ui",
90
+ "title": "Alert",
91
+ "description": "Persistent inline notice primitive. Four intents (info / success / warning / destructive) with mapped lucide icons (Info / CheckCircle2 / TriangleAlert / AlertCircle) and design tokens. Optional title, description, action slot, and onDismiss handler. destructive intent renders role=alert (assertive); other intents render role=status (polite). Distinct from Toast (transient, auto-dismiss) and EmptyState (centered card)."
92
+ },
87
93
  {
88
94
  "name": "approval-card",
89
95
  "type": "registry:block",
@@ -192,12 +198,24 @@
192
198
  "title": "cn (Tailwind class merger)",
193
199
  "description": "Merge Tailwind classes with conflict resolution."
194
200
  },
201
+ {
202
+ "name": "code-block",
203
+ "type": "registry:ui",
204
+ "title": "CodeBlock",
205
+ "description": "Terminal / code-snippet surface. Renders code inside a <pre> with optional 'terminal' prefix per line ('$ '), optional caption (file name), and optional inline CopyButton in top-right. Copy uses the raw code (without the visual prefix). language prop is forward-compat for future syntax highlighting."
206
+ },
195
207
  {
196
208
  "name": "command-palette",
197
209
  "type": "registry:ui",
198
210
  "title": "CommandPalette",
199
211
  "description": "Cmd+K-style global launcher with arrow-key navigation, fuzzy ranking, and Enter/Escape behavior — built on cmdk + Theo Dialog."
200
212
  },
213
+ {
214
+ "name": "confirm-dialog",
215
+ "type": "registry:ui",
216
+ "title": "ConfirmDialog",
217
+ "description": "Controlled confirmation modal built on Dialog. Auto-focuses Cancel on open (deliberate — NOT the destructive button). Optional intent=destructive switches the confirm button to destructive variant. Optional confirmationPhrase enables typed-confirmation guard (case-sensitive, empty string = no phrase). Async onConfirm shows Loader2 spinner; resolve closes the dialog; reject keeps it open so consumers can surface their own error. Enter in the phrase input triggers confirm when matched."
218
+ },
201
219
  {
202
220
  "name": "context-card",
203
221
  "type": "registry:ui",
@@ -210,6 +228,12 @@
210
228
  "title": "ContextWindowBar",
211
229
  "description": "Shows how much of the model's context window has been"
212
230
  },
231
+ {
232
+ "name": "copy-button",
233
+ "type": "registry:ui",
234
+ "title": "CopyButton",
235
+ "description": "Click-to-copy button primitive. Wraps navigator.clipboard.writeText with icon swap (Copy → Check on success, Copy → X on failure), aria-live announcement for screen readers, optional label, ghost/outline variants, and SSR-safe rendering. Auto-cleans the revert timer on unmount and debounces double-clicks."
236
+ },
213
237
  {
214
238
  "name": "cost-meter",
215
239
  "type": "registry:ui",
@@ -234,6 +258,12 @@
234
258
  "title": "CronJobsList",
235
259
  "description": "Grid of CronJobCards with a sticky \"new job\" action."
236
260
  },
261
+ {
262
+ "name": "danger-zone",
263
+ "type": "registry:ui",
264
+ "title": "DangerZone",
265
+ "description": "Destructive-actions section primitive with sub-component DangerZone.Action. Red-bordered container with title bar (default 'Danger Zone') and action rows. Each row carries title + description + consumer-provided action slot (typically a destructive Button). Rows separated by hairline dividers; last row drops the bottom border via last:border-b-0."
266
+ },
237
267
  {
238
268
  "name": "deployment-row",
239
269
  "type": "registry:block",
@@ -384,6 +414,12 @@
384
414
  "title": "ModelSelector",
385
415
  "description": "Chip dropdown for picking the active LLM."
386
416
  },
417
+ {
418
+ "name": "pagination",
419
+ "type": "registry:ui",
420
+ "title": "Pagination",
421
+ "description": "Accessible page-number navigation primitive. Renders <nav aria-label=Pagination> with first/prev/numbers/next/last buttons and visual ellipses when totalPages exceeds the visible range. Active page carries aria-current=page. Keyboard nav: ArrowLeft / ArrowRight / Home / End. Configurable siblingCount + optional jump buttons. Returns null when totalPages <= 1. Exports a pure computePageRange helper for unit testing the range logic in isolation."
422
+ },
387
423
  {
388
424
  "name": "permission-matrix",
389
425
  "type": "registry:ui",
@@ -606,6 +642,18 @@
606
642
  "title": "SocialAuthRow",
607
643
  "description": "Row of OAuth provider buttons."
608
644
  },
645
+ {
646
+ "name": "stat-tile",
647
+ "type": "registry:ui",
648
+ "title": "StatTile",
649
+ "description": "Big-number stat tile primitive for dashboard summaries. Renders value + label + optional icon + optional delta (trend up/down/flat with TrendingUp/TrendingDown/Minus icons and success/destructive/muted color). Dual mode: with onClick renders as button with hover state + trailing ArrowUpRight chevron; without, renders as static div. Value uses font-display tabular-nums whitespace-nowrap."
650
+ },
651
+ {
652
+ "name": "status-dot",
653
+ "type": "registry:ui",
654
+ "title": "StatusDot",
655
+ "description": "Semantic status indicator (small colored circle + optional label). Five status kinds: live (success), building (warning, auto-pulses), failed (destructive), idle (muted), warning (warning, static). Three sizes (xs 6px / sm 8px default / md 10px). When neither label nor aria-label is provided, auto-applies aria-label=status and emits a dev warning."
656
+ },
609
657
  {
610
658
  "name": "steps-rail",
611
659
  "type": "registry:ui",
@@ -630,6 +678,12 @@
630
678
  "title": "SystemPromptEditor",
631
679
  "description": "Surface the agent's system prompt with a clear"
632
680
  },
681
+ {
682
+ "name": "table",
683
+ "type": "registry:ui",
684
+ "title": "Table",
685
+ "description": "Semantic data-table primitive with sub-components (Table.Header, Table.Body, Table.Row, Table.Cell, Table.HeaderCell). Supports density (default | compact via Context), per-cell align (left | center | right), numeric cells (font-mono tabular-nums), and sortable header cells (onSort + sortDirection with ChevronUp/ChevronDown affordance + aria-sort)."
686
+ },
633
687
  {
634
688
  "name": "tabs",
635
689
  "type": "registry:ui",
@@ -690,6 +744,12 @@
690
744
  "title": "TheoUIProvider",
691
745
  "description": "Primary entry-point provider — composes ThemeProvider + Toaster with sensible defaults. Use as the single root wrapper in consumer apps."
692
746
  },
747
+ {
748
+ "name": "timestamp",
749
+ "type": "registry:ui",
750
+ "title": "Timestamp",
751
+ "description": "Accessible <time> primitive with relative/absolute/both formats, auto-refresh interval (default 60s, 0 disables), native title tooltip with absolute time, and aria-label that always carries the full date. Built on Intl.RelativeTimeFormat (zero deps). value accepts ISO string, Date, or Unix ms (NOT seconds). Invalid date renders empty element; invalid locale falls back to default with dev warning."
752
+ },
693
753
  {
694
754
  "name": "toast",
695
755
  "type": "registry:ui",
@@ -3,7 +3,7 @@
3
3
  "name": "account-menu",
4
4
  "type": "registry:ui",
5
5
  "title": "AccountMenu",
6
- "description": "Sidebar header for PaaS surfaces. Avatar + name + (optional) PlanBadge + (optional) secondary line, with dual mode: with onClick renders as a <button> with trailing chevron (account picker affordance); without, renders as a static <div>. PaaS-shape sibling of ProjectSwitcher.",
6
+ "description": "Sidebar header for PaaS surfaces. Avatar + name + (optional) PlanBadge + (optional) secondary line, with dual mode: with onClick renders as a `button` with trailing chevron (account picker affordance); without, renders as a static `div`. PaaS-shape sibling of ProjectSwitcher.",
7
7
  "dependencies": [
8
8
  "lucide-react"
9
9
  ],