chore(webui): scaffold @ironclaw/ui design-system package (Phase 3 reference)

Adds crates/product/ironclaw_webui/frontend/packages/ui/ — the target structure for
the design system as a first-class package (tokens/ themes/ icons/ components/<name>/),
as an inert reference for the Phase-3 reskin (Epic #7038). Every file is a stub; the
package is intentionally NOT wired into pnpm-workspace, the Storybook glob, or tsconfig,
so it neither builds nor runs yet — typecheck and vitest are both src-scoped and ignore it.

Supersedes the closed #6836 (@ironclaw/ui workspace refactor).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ron
2026-08-12 14:57:44 -07:00
parent ee3146af9b
commit dabcf71a88
52 changed files with 155 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
# `@ironclaw/ui` — design-system package (scaffold)
Target home for the IronClaw WebUI design system as a first-class package,
scaffolded now as a **reference for the Phase-3 reskin** (Epic
[#7038](https://github.com/nearai/ironclaw/issues/7038)). This is the framework
the current `../../src/design-system/` primitives migrate **into** over Phases
34.
> **Status: inert scaffold — not yet wired.** Every file here is a stub. The
> package is deliberately **not** in `pnpm-workspace.yaml`, the Storybook stories
> glob, or `tsconfig.json`, so it neither builds nor runs today. Phase 3 wires it
> in (workspace member → tokens → components), one component at a time.
## Structure
```
packages/ui/src/
├── tokens/ colors · typography · spacing · radii · shadows · motion (one .css per token layer)
├── themes/ light.css · dark.css · themes.stories.tsx (theme token values + preview)
├── icons/ icon.tsx · registry.ts · icons.stories.tsx · index.ts
├── components/ button · input · select · card · modal · badge · switch (one folder each)
│ └── button/ button.tsx · button.variants.ts · button.stories.tsx · button.test.tsx · index.ts
└── styles/ index.css (package style entry: @imports the token + theme layers)
```
**Per-component convention** (see `components/button/` as the worked template):
| File | Role |
|------|------|
| `<name>.tsx` | The component — presentational; styled through tokens, never hardcoded hex/px |
| `<name>.variants.ts` | Variant/size map (cva-style) kept out of the component body |
| `<name>.stories.tsx` | Storybook catalog entry (smoke + variant + `play` where it proves something) |
| `<name>.test.tsx` | Unit test |
| `index.ts` | Public re-export |
## Migration mapping (Phase 3)
| Today (`src/design-system/`) | Target (`packages/ui/src/`) |
|---|---|
| `app.css` `@theme` + `--v2-*` (in `src/styles/`) | `tokens/*.css` + `themes/{light,dark}.css` |
| `button.tsx`, `input.tsx`, `select-menu.tsx`, `card.tsx`, `modal.tsx`, `badge.tsx`, `switch.tsx` | `components/<name>/` |
| `icons.tsx` | `icons/` |
| `*.stories.tsx` (colocated) | colocated in each `components/<name>/` |
| `src/test-support/storybook-decorators.tsx` | `.storybook/decorators.tsx` (shared) |
## Rules
Governed by [`DESIGN.md`](../../DESIGN.md) and
[`.claude/rules/design-system.md`](../../../../../../.claude/rules/design-system.md):
native M3X on React + Tailwind, token-driven (no hardcoded hex/px), a story per
component, WCAG AA + light/dark parity, `prefers-reduced-motion`-gated motion.

View File

@@ -0,0 +1,16 @@
{
"name": "@ironclaw/ui",
"version": "0.0.0",
"private": true,
"description": "IronClaw WebUI design-system package (@ironclaw/ui) — Phase-3 scaffold. Not yet wired into the build (see README).",
"type": "module",
"exports": {
".": "./src/index.ts",
"./styles": "./src/styles/index.css",
"./tokens/*": "./src/tokens/*"
},
"peerDependencies": {
"react": "^19",
"react-dom": "^19"
}
}

View File

@@ -0,0 +1 @@
// badge.stories.tsx (Phase 3). Template: src/design-system/badge.stories.tsx

View File

@@ -0,0 +1 @@
// badge.test.tsx (Phase 3). Template: src/design-system/badge.test.tsx

View File

@@ -0,0 +1,2 @@
// @ironclaw/ui <badge> (Phase 3). Migrate from src/design-system/badge.tsx; style via tokens, not hex/px.
export {};

View File

@@ -0,0 +1,2 @@
// badge variant map (cva-style) (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Public badge export (Phase 3).
export {};

View File

@@ -0,0 +1 @@
// button.stories.tsx (Phase 3). Template: src/design-system/button.stories.tsx

View File

@@ -0,0 +1 @@
// button.test.tsx (Phase 3). Template: src/design-system/button.test.tsx

View File

@@ -0,0 +1,2 @@
// @ironclaw/ui <button> (Phase 3). Migrate from src/design-system/button.tsx; style via tokens, not hex/px.
export {};

View File

@@ -0,0 +1,2 @@
// button variant map (cva-style) (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Public button export (Phase 3).
export {};

View File

@@ -0,0 +1 @@
// card.stories.tsx (Phase 3). Template: src/design-system/card.stories.tsx

View File

@@ -0,0 +1 @@
// card.test.tsx (Phase 3). Template: src/design-system/card.test.tsx

View File

@@ -0,0 +1,2 @@
// @ironclaw/ui <card> (Phase 3). Migrate from src/design-system/card.tsx; style via tokens, not hex/px.
export {};

View File

@@ -0,0 +1,2 @@
// card variant map (cva-style) (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Public card export (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Public input export (Phase 3).
export {};

View File

@@ -0,0 +1 @@
// input.stories.tsx (Phase 3). Template: src/design-system/input.stories.tsx

View File

@@ -0,0 +1 @@
// input.test.tsx (Phase 3). Template: src/design-system/input.test.tsx

View File

@@ -0,0 +1,2 @@
// @ironclaw/ui <input> (Phase 3). Migrate from src/design-system/input.tsx; style via tokens, not hex/px.
export {};

View File

@@ -0,0 +1,2 @@
// input variant map (cva-style) (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Public modal export (Phase 3).
export {};

View File

@@ -0,0 +1 @@
// modal.stories.tsx (Phase 3). Template: src/design-system/modal.stories.tsx

View File

@@ -0,0 +1 @@
// modal.test.tsx (Phase 3). Template: src/design-system/modal.test.tsx

View File

@@ -0,0 +1,2 @@
// @ironclaw/ui <modal> (Phase 3). Migrate from src/design-system/modal.tsx; style via tokens, not hex/px.
export {};

View File

@@ -0,0 +1,2 @@
// modal variant map (cva-style) (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Public select export (Phase 3).
export {};

View File

@@ -0,0 +1 @@
// select.stories.tsx (Phase 3). Template: src/design-system/select.stories.tsx

View File

@@ -0,0 +1 @@
// select.test.tsx (Phase 3). Template: src/design-system/select.test.tsx

View File

@@ -0,0 +1,2 @@
// @ironclaw/ui <select> (Phase 3). Migrate from src/design-system/select.tsx; style via tokens, not hex/px.
export {};

View File

@@ -0,0 +1,2 @@
// select variant map (cva-style) (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Public switch export (Phase 3).
export {};

View File

@@ -0,0 +1 @@
// switch.stories.tsx (Phase 3). Template: src/design-system/switch.stories.tsx

View File

@@ -0,0 +1 @@
// switch.test.tsx (Phase 3). Template: src/design-system/switch.test.tsx

View File

@@ -0,0 +1,2 @@
// @ironclaw/ui <switch> (Phase 3). Migrate from src/design-system/switch.tsx; style via tokens, not hex/px.
export {};

View File

@@ -0,0 +1,2 @@
// switch variant map (cva-style) (Phase 3).
export {};

View File

@@ -0,0 +1 @@
// @ironclaw/ui Icon (Phase 3). Template: src/design-system/icons.tsx

View File

@@ -0,0 +1 @@
// icons.stories.tsx — Icons gallery (Phase 3). Template: src/design-system/icons.stories.tsx

View File

@@ -0,0 +1,2 @@
// Public icon exports (Phase 3).
export {};

View File

@@ -0,0 +1,2 @@
// Icon name -> glyph registry (Phase 3).
export const iconRegistry = {} as const;

View File

@@ -0,0 +1,9 @@
// @ironclaw/ui — public API (Phase 3).
//
// Populated as components migrate out of ../../src/design-system/ into
// ./components/<name>/. Until then this is an inert scaffold entry point.
//
// export * from "./components/button";
// export * from "./components/input";
// export * from "./icons";
export {};

View File

@@ -0,0 +1 @@
/* @ironclaw/ui — package style entry (Phase 3): @import token + theme layers here. */

View File

@@ -0,0 +1 @@
/* @ironclaw/ui — dark theme token values (Phase 3). Derive from app.css :root[data-theme="dark"]. */

View File

@@ -0,0 +1 @@
/* @ironclaw/ui — light theme token values (Phase 3). Derive from app.css :root. */

View File

@@ -0,0 +1,2 @@
// themes.stories.tsx — Storybook 'Tokens/Themes' preview (Phase 3).
// Template: src/design-system/tokens-colors.stories.tsx

View File

@@ -0,0 +1,2 @@
/* @ironclaw/ui — colors tokens (Phase 3 target).
Migrate the matching values from ../../../../src/styles/app.css (@theme + --v2-*). */

View File

@@ -0,0 +1,2 @@
/* @ironclaw/ui — motion tokens (Phase 3 target).
Migrate the matching values from ../../../../src/styles/app.css (@theme + --v2-*). */

View File

@@ -0,0 +1,2 @@
/* @ironclaw/ui — radii tokens (Phase 3 target).
Migrate the matching values from ../../../../src/styles/app.css (@theme + --v2-*). */

View File

@@ -0,0 +1,2 @@
/* @ironclaw/ui — shadows tokens (Phase 3 target).
Migrate the matching values from ../../../../src/styles/app.css (@theme + --v2-*). */

View File

@@ -0,0 +1,2 @@
/* @ironclaw/ui — spacing tokens (Phase 3 target).
Migrate the matching values from ../../../../src/styles/app.css (@theme + --v2-*). */

View File

@@ -0,0 +1,2 @@
/* @ironclaw/ui — typography tokens (Phase 3 target).
Migrate the matching values from ../../../../src/styles/app.css (@theme + --v2-*). */