From dabcf71a884a941a8a00f6aaa32544141e2feab1 Mon Sep 17 00:00:00 2001 From: Ron Date: Wed, 12 Aug 2026 14:57:44 -0700 Subject: [PATCH] chore(webui): scaffold @ironclaw/ui design-system package (Phase 3 reference) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds crates/product/ironclaw_webui/frontend/packages/ui/ — the target structure for the design system as a first-class package (tokens/ themes/ icons/ components//), 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 --- .../frontend/packages/ui/README.md | 51 +++++++++++++++++++ .../frontend/packages/ui/package.json | 16 ++++++ .../ui/src/components/badge/badge.stories.tsx | 1 + .../ui/src/components/badge/badge.test.tsx | 1 + .../ui/src/components/badge/badge.tsx | 2 + .../ui/src/components/badge/badge.variants.ts | 2 + .../packages/ui/src/components/badge/index.ts | 2 + .../src/components/button/button.stories.tsx | 1 + .../ui/src/components/button/button.test.tsx | 1 + .../ui/src/components/button/button.tsx | 2 + .../src/components/button/button.variants.ts | 2 + .../ui/src/components/button/index.ts | 2 + .../ui/src/components/card/card.stories.tsx | 1 + .../ui/src/components/card/card.test.tsx | 1 + .../packages/ui/src/components/card/card.tsx | 2 + .../ui/src/components/card/card.variants.ts | 2 + .../packages/ui/src/components/card/index.ts | 2 + .../packages/ui/src/components/input/index.ts | 2 + .../ui/src/components/input/input.stories.tsx | 1 + .../ui/src/components/input/input.test.tsx | 1 + .../ui/src/components/input/input.tsx | 2 + .../ui/src/components/input/input.variants.ts | 2 + .../packages/ui/src/components/modal/index.ts | 2 + .../ui/src/components/modal/modal.stories.tsx | 1 + .../ui/src/components/modal/modal.test.tsx | 1 + .../ui/src/components/modal/modal.tsx | 2 + .../ui/src/components/modal/modal.variants.ts | 2 + .../ui/src/components/select/index.ts | 2 + .../src/components/select/select.stories.tsx | 1 + .../ui/src/components/select/select.test.tsx | 1 + .../ui/src/components/select/select.tsx | 2 + .../src/components/select/select.variants.ts | 2 + .../ui/src/components/switch/index.ts | 2 + .../src/components/switch/switch.stories.tsx | 1 + .../ui/src/components/switch/switch.test.tsx | 1 + .../ui/src/components/switch/switch.tsx | 2 + .../src/components/switch/switch.variants.ts | 2 + .../frontend/packages/ui/src/icons/icon.tsx | 1 + .../packages/ui/src/icons/icons.stories.tsx | 1 + .../frontend/packages/ui/src/icons/index.ts | 2 + .../packages/ui/src/icons/registry.ts | 2 + .../frontend/packages/ui/src/index.ts | 9 ++++ .../frontend/packages/ui/src/styles/index.css | 1 + .../frontend/packages/ui/src/themes/dark.css | 1 + .../frontend/packages/ui/src/themes/light.css | 1 + .../packages/ui/src/themes/themes.stories.tsx | 2 + .../packages/ui/src/tokens/colors.css | 2 + .../packages/ui/src/tokens/motion.css | 2 + .../frontend/packages/ui/src/tokens/radii.css | 2 + .../packages/ui/src/tokens/shadows.css | 2 + .../packages/ui/src/tokens/spacing.css | 2 + .../packages/ui/src/tokens/typography.css | 2 + 52 files changed, 155 insertions(+) create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/README.md create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/package.json create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.test.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.variants.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.test.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.variants.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/card/card.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/card/card.test.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/card/card.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/card/card.variants.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/card/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/input/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/input/input.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/input/input.test.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/input/input.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/input/input.variants.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/modal/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/modal/modal.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/modal/modal.test.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/modal/modal.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/modal/modal.variants.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/select/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/select/select.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/select/select.test.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/select/select.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/select/select.variants.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/switch/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/switch/switch.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/switch/switch.test.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/switch/switch.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/components/switch/switch.variants.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/icons/icon.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/icons/icons.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/icons/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/icons/registry.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/index.ts create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/styles/index.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/themes/dark.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/themes/light.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/themes/themes.stories.tsx create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/tokens/colors.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/tokens/motion.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/tokens/radii.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/tokens/shadows.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/tokens/spacing.css create mode 100644 crates/product/ironclaw_webui/frontend/packages/ui/src/tokens/typography.css diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/README.md b/crates/product/ironclaw_webui/frontend/packages/ui/README.md new file mode 100644 index 0000000000..cca350e6bc --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/README.md @@ -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 +3–4. + +> **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 | +|------|------| +| `.tsx` | The component — presentational; styled through tokens, never hardcoded hex/px | +| `.variants.ts` | Variant/size map (cva-style) kept out of the component body | +| `.stories.tsx` | Storybook catalog entry (smoke + variant + `play` where it proves something) | +| `.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//` | +| `icons.tsx` | `icons/` | +| `*.stories.tsx` (colocated) | colocated in each `components//` | +| `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. diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/package.json b/crates/product/ironclaw_webui/frontend/packages/ui/package.json new file mode 100644 index 0000000000..cdf961fd4a --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/package.json @@ -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" + } +} diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.stories.tsx b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.stories.tsx new file mode 100644 index 0000000000..acf96c6d39 --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.stories.tsx @@ -0,0 +1 @@ +// badge.stories.tsx (Phase 3). Template: src/design-system/badge.stories.tsx diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.test.tsx b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.test.tsx new file mode 100644 index 0000000000..8c977ae54b --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.test.tsx @@ -0,0 +1 @@ +// badge.test.tsx (Phase 3). Template: src/design-system/badge.test.tsx diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.tsx b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.tsx new file mode 100644 index 0000000000..ff23c912d5 --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.tsx @@ -0,0 +1,2 @@ +// @ironclaw/ui (Phase 3). Migrate from src/design-system/badge.tsx; style via tokens, not hex/px. +export {}; diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.variants.ts b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.variants.ts new file mode 100644 index 0000000000..db048cda8a --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/badge.variants.ts @@ -0,0 +1,2 @@ +// badge variant map (cva-style) (Phase 3). +export {}; diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/index.ts b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/index.ts new file mode 100644 index 0000000000..ecc6b0aa18 --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/badge/index.ts @@ -0,0 +1,2 @@ +// Public badge export (Phase 3). +export {}; diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.stories.tsx b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.stories.tsx new file mode 100644 index 0000000000..1be29fd7d2 --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.stories.tsx @@ -0,0 +1 @@ +// button.stories.tsx (Phase 3). Template: src/design-system/button.stories.tsx diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.test.tsx b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.test.tsx new file mode 100644 index 0000000000..3d9a9a3b44 --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.test.tsx @@ -0,0 +1 @@ +// button.test.tsx (Phase 3). Template: src/design-system/button.test.tsx diff --git a/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.tsx b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.tsx new file mode 100644 index 0000000000..7e3941880c --- /dev/null +++ b/crates/product/ironclaw_webui/frontend/packages/ui/src/components/button/button.tsx @@ -0,0 +1,2 @@ +// @ironclaw/ui