feat(ui): add analytics primitives and layout patterns

This commit is contained in:
2026-03-25 19:49:49 +08:00
parent cc1509d2f6
commit a5d75f42e9
63 changed files with 7751 additions and 2 deletions
@@ -0,0 +1,62 @@
# Challenge Progress Pattern
- Status: `completed`
- Owner: `Codex`
- Date: `2026-03-25`
## Goal
Add a reusable `ChallengeProgress` pattern to `packages/ui` that recreates the stacked challenge
target panel shown in the reference, while staying inside Cadence UI's own tonal, rounded, and
component-first visual language.
## Scope
- In scope:
- add a new `ChallengeProgress` pattern for multi-row target progress panels
- compose the pattern from existing Cadence UI primitives where practical, especially `Badge`,
`Progress`, and `Spinner`
- add tests and Storybook docs for the new pattern
- export the pattern from `@ai-ui/ui`
- Out of scope:
- changing the base `Progress` contract or segment-count limits
- adding a new shared icon package or icon primitives
- registry metadata refresh while the worktree already carries unrelated registry changes
## Constraints
- Keep the pattern visually aligned with `DESIGN.md`, not the dark reference palette.
- Prefer stable slots and data attributes over story-local styling glue.
- Preserve the dirty worktree and avoid rewriting unrelated in-flight edits.
- Use the smallest new API surface that can still support multiple challenge rows.
## Affected Surfaces
- `packages/ui/src/patterns/challenge-progress.tsx`
- `packages/ui/src/patterns/challenge-progress.variants.ts`
- `packages/ui/src/patterns/challenge-progress.test.tsx`
- `packages/ui/src/index.ts`
- `apps/docs/src/patterns/challenge-progress.stories.tsx`
## Plan
1. Define the pattern API and slot structure around a title plus repeated challenge rows.
2. Implement the pattern styling with existing tokens and compose row status from existing
primitives.
3. Add unit coverage and Storybook docs showing the reference-inspired layout in Cadence UI's own
palette.
4. Run targeted validation for the new pattern, exports, and docs surface.
## Validation
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm --filter @ai-ui/ui exec vitest run packages/ui/src/patterns/challenge-progress.test.tsx --config ../../vitest.config.ts`
- `pnpm exec eslint apps/docs/src/patterns/challenge-progress.stories.tsx packages/ui/src/patterns/challenge-progress.tsx packages/ui/src/patterns/challenge-progress.variants.ts packages/ui/src/patterns/challenge-progress.test.tsx packages/ui/src/index.ts`
- `pnpm harness:validate:docs`
## Status Log
- `2026-03-25 19:44` Read the required system-of-record files, inspected the existing `Progress`, `Badge`, `Spinner`, and pattern authoring conventions, and scoped the work as a new reusable pattern instead of a one-off story.
- `2026-03-25 20:20` Implemented the `ChallengeProgress` pattern and variants around a title plus repeated challenge rows, composing row chips from `Badge`, row meters from segmented `Progress`, and loading affordances from `Spinner`.
- `2026-03-25 20:24` Added unit coverage, Storybook docs, and package exports for the new pattern.
- `2026-03-25 20:26` Verified `pnpm --filter @ai-ui/ui typecheck`, targeted `vitest`, targeted `eslint`, and `pnpm harness:validate:docs`.
@@ -0,0 +1,77 @@
# Chart Pattern
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a reusable `Chart` pattern to `@ai-ui/ui` that can render the kind of dashboard trend panel
shown in the supplied reference: multi-series lines, soft area shading, an active point summary,
and a composable card-like review surface that still follows Cadence UI's current visual language.
## Scope
- In scope:
- add a new `Chart` component to `packages/ui`
- keep the first release focused on cartesian trend charts for dashboard analytics surfaces
- support multi-series rendering, optional area fills, axes, legend, and active-point callouts
- add Storybook stories, including a `Sales Impact`-style showcase
- add unit coverage for the public contract and interactive active-point behavior
- refresh repo status docs to reflect the shipped pattern
- Out of scope:
- introducing a third-party charting dependency
- building a full visualization framework with bars, pies, heatmaps, and pivoting
- server-driven drilldown, zooming, panning, or data transforms outside the component
- adding the new story to the curated browser harness unless it becomes a required regression
surface
## Constraints
- Follow `DESIGN.md` over the raw screenshot when visual details conflict.
- Reuse existing tokens, motion rules, and card-like surface styling instead of hardcoded brand
treatments.
- Keep the API source-owned and narrow, similar to the `DataTable` philosophy.
- Preserve stable `data-slot` and `data-*` hooks so docs and tests can target the component
predictably.
## Affected Surfaces
- `docs/exec-plans/2026-03-25-chart-pattern.md`
- `packages/ui/src/components/chart.tsx`
- `packages/ui/src/components/chart.variants.ts`
- `packages/ui/src/components/chart.test.tsx`
- `packages/ui/src/index.ts`
- `apps/docs/src/components/chart.stories.tsx`
- `README.md`
- `roadmap.md`
- `registry/index.json`
## Plan
1. Add an execution plan and update repo status docs for the new public pattern.
2. Implement a source-owned `Chart` component that supports multi-series dashboard trend charts
without adding an external chart library.
3. Add Storybook stories that explain anatomy and demonstrate a `Sales Impact`-style analytics
panel.
4. Add unit tests for slots, legend rendering, active-point updates, and controlled state.
5. Run the narrowest useful validation suites, then record any remaining gaps.
## Validation
- `pnpm test -- --runInBand`
- `pnpm harness:validate:docs`
- `pnpm registry:build`
## Orchestration Task Sketch
- `T1`: implement the Chart component and export surface
- `T2 -> T1`: add docs stories and validate the rendered showcase
- `T3 -> T1`: add tests and registry updates
## Status Log
- `2026-03-25 19:08` Read the system-of-record files and confirmed the repo does not yet ship a chart pattern.
- `2026-03-25 19:18` Started the chart implementation plan for a new dashboard-focused analytics pattern.
- `2026-03-25 19:42` Implemented the new `Chart` component, public exports, stories, tests, and status-doc updates.
- `2026-03-25 19:55` Validated `packages/ui` typecheck, targeted chart tests, package builds, Storybook docs build, and registry generation. `pnpm harness:validate:changed` still failed because the dirty worktree already contains unrelated `apps/docs/src/revenue-dashboard.stories.tsx` type errors and existing `react-refresh/only-export-components` warnings in `packages/ui/src/components/context-menu.tsx`.
@@ -0,0 +1,71 @@
# Dashboard Contract Hardening
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Harden the new dashboard-oriented component contracts so the `Revenue Dashboard` scene no longer
needs to bypass them for high-emphasis KPI cards or for custom chart header layouts.
## Scope
- In scope:
- extend `MetricCard` with high-emphasis tones suitable for dark or hero KPI panels
- add structured `MetricCard` header slots for leading and aside content
- make the `Chart` header composable without breaking the current convenience props
- refresh docs stories, tests, and the revenue dashboard consumer to use the stronger contracts
- Out of scope:
- introducing a full dashboard layout or navigation system
- expanding the chart surface beyond the existing cartesian trend pattern
- extracting new sparkline or sparkbar primitives in this slice
## Constraints
- Preserve the current Material-inspired design direction in `DESIGN.md`.
- Keep the API additive and source-owned instead of replacing existing stories with one-off markup.
- Preserve the stable slot and `data-*` review surface so tests and docs stay predictable.
- Keep the current `title` / `description` / `value` / `valueChange` chart props working while
adding the more composable header path.
## Affected Surfaces
- `docs/exec-plans`
- `packages/ui/src/components/metric-card.tsx`
- `packages/ui/src/components/metric-card.variants.ts`
- `packages/ui/src/components/chart.tsx`
- `packages/ui/src/components/chart.variants.ts`
- `packages/ui/src/index.ts`
- `packages/ui/src/components/*.test.tsx`
- `apps/docs/src/components/*.stories.tsx`
- `apps/docs/src/revenue-dashboard.stories.tsx`
## Plan
1. Extend `MetricCard` with `inverse` and `hero` visual tones plus stable `leading` and `aside`
header slots.
2. Refactor `Chart` to accept a composed header while keeping the current prop-based header API as
a convenience fallback.
3. Update stories and the revenue dashboard scene so the new contracts are exercised by real
compositions instead of only isolated tests.
4. Run focused component and docs validation, then record any residual issues.
## Validation
- `pnpm --filter @ai-ui/ui test -- metric-card chart`
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm build:docs`
## Orchestration Task Sketch
- `T1`: harden `MetricCard` tone and header composition contract
- `T2 -> T1`: harden `Chart` header composition contract
- `T3 -> T2`: refresh stories, revenue dashboard usage, and focused validation
## Status Log
- `2026-03-25 20:36` started the contract-hardening slice after reviewing the revenue dashboard and confirming that `Sales Growth` and `Sales Impact` still rely on API workarounds rather than first-class component affordances
- `2026-03-25 20:49` extended `MetricCard` with `inverse` and `hero` tones plus `leading` and `aside` header slots, then refactored the docs story and revenue dashboard consumer to use them
- `2026-03-25 20:56` refactored `Chart` to support a composed header path while preserving the legacy prop-driven header contract, and updated stories and tests to cover both paths
- `2026-03-25 20:59` validated focused `MetricCard` and `Chart` tests plus `build:docs`; `pnpm --filter @ai-ui/ui typecheck` is still blocked by unrelated pre-existing `packages/ui/src/components/sparkbar.tsx` type errors outside this slice
@@ -0,0 +1,59 @@
# Gauge Component
- Status: `completed`
- Owner: `Codex`
- Date: `2026-03-25`
## Goal
Add a true radial `Gauge` component to `packages/ui` so the system supports meter-style KPI
visuals in addition to linear `Progress` and segmented progress bars.
## Scope
- In scope:
- add a new `Gauge` component with radial SVG rendering
- support dial and semi-circle shapes
- cover the component with tests and Storybook docs
- export the component from `@ai-ui/ui`
- Out of scope:
- registry metadata refresh while the worktree already contains unrelated registry edits
- retrofitting local draft dashboard stories to use the new component
- animated needle / pointer gauges
## Constraints
- `Gauge` should use `role="meter"` rather than overloading `Progress`.
- Keep `variant` semantic and reserve geometry differences for a dedicated shape dimension.
- Follow the current Cadence UI tonal and motion language.
- Preserve the existing dirty worktree and avoid rewriting unrelated draft files.
## Affected Surfaces
- `packages/ui/src/components/gauge.tsx`
- `packages/ui/src/components/gauge.variants.ts`
- `packages/ui/src/components/gauge.test.tsx`
- `packages/ui/src/skins.css`
- `packages/ui/src/index.ts`
- `apps/docs/src/components/gauge.stories.tsx`
## Plan
1. Define the Gauge API, rendering geometry, and stable slots.
2. Implement the component with skin tokens and SVG arc math.
3. Add tests and Storybook docs for geometry, states, and accessibility guidance.
4. Run targeted validation for the package surface and changed files.
## Validation
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm --filter @ai-ui/ui build`
- `pnpm --filter @ai-ui/ui exec vitest run packages/ui/src/components/gauge.test.tsx --config ../../vitest.config.ts`
- `pnpm exec eslint apps/docs/src/components/gauge.stories.tsx packages/ui/src/components/gauge.tsx packages/ui/src/components/gauge.variants.ts packages/ui/src/components/gauge.test.tsx packages/ui/src/index.ts`
## Status Log
- `2026-03-25 18:30` Read the closest dashboard-oriented component and story patterns, and scoped Gauge as a separate meter primitive rather than an extension of Progress.
- `2026-03-25 18:42` Implemented the `Gauge` component with radial SVG geometry, dial and semi-circle shapes, meter semantics, and stable slots.
- `2026-03-25 18:47` Added package exports, skin tokens, unit coverage, and a dedicated Storybook docs page for Gauge.
- `2026-03-25 18:51` Verified `pnpm --filter @ai-ui/ui typecheck`, `pnpm --filter @ai-ui/ui build`, `pnpm --filter @ai-ui/ui exec vitest run packages/ui/src/components/gauge.test.tsx --config ../../vitest.config.ts`, targeted `eslint`, and `pnpm harness:validate:docs`.
@@ -0,0 +1,73 @@
# Grid Primitives
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add Cadence UI source-owned `Row` / `Col` grid primitives so product and docs surfaces can build
responsive split layouts and dashboard sections without repeating ad hoc width math, alignment
fixes, or one-off `grid-cols-*` strings.
## Scope
- In scope:
- add public `Row` and `Col` primitives to `packages/ui`
- support a 12-column responsive layout model with tokenized gaps
- support base plus breakpoint-specific `span` and `offset` placement on `Col`
- expose stable slot and `data-*` hooks
- document the primitives in Storybook
- add unit coverage for the main layout contract
- Out of scope:
- nested layout orchestration helpers such as `SplitPanel` or dialog-specific shells
- CSS container-query driven layout APIs
- ordering, push/pull, or visual reordering props that can drift from DOM order
- replacing every existing docs layout in this pass
## Constraints
- Keep the API small and familiar to teams coming from Ant Design / Element style `Row` / `Col`.
- Stay token-first for spacing instead of baking new hardcoded per-story gutters.
- Preserve DOM order as the semantic order; layout props should not encourage accessibility drift.
- Avoid introducing an external layout framework or dependency for this capability.
## Affected Surfaces
- `packages/ui/src/components`
- `packages/ui/src/index.ts`
- `packages/ui/src/lib/contracts.ts`
- `packages/ui/src/skins.css`
- `apps/docs/src/components`
- `docs/exec-plans`
- `registry/index.json`
## Plan
1. Add the execution plan and define a minimal Cadence UI grid contract.
2. Implement `Row` and `Col` with a 12-column base, tokenized gap sizes, and responsive
`span` / `offset` placement.
3. Export the primitives on the public surface and document them in Storybook with usage,
anatomy, and accessibility guidance.
4. Add focused unit coverage, run narrow validation, then rebuild registry metadata for the
new public entrypoint.
## Validation
- `pnpm --filter @ai-ui/ui test -- grid`
- `pnpm build:docs`
- `pnpm registry:build`
## Orchestration Task Sketch
- `T1`: implement the grid primitives, skins, and public exports
- `T2 -> T1`: add Storybook docs, tests, and rebuild registry metadata
## Status Log
- `2026-03-25 16:18` started after confirming the repo has many direct grid utility usages but no
reusable source-owned layout primitive for responsive row/column composition
- `2026-03-25 18:54` implemented public `Row` / `Col` primitives, exported them from `@ai-ui/ui`,
added Storybook coverage, and registered the new source-owned `grid` entrypoint
- `2026-03-25 18:56` validated with `pnpm --filter @ai-ui/ui test -- grid`,
`pnpm --filter @ai-ui/ui build`, `pnpm build:docs`, and `pnpm registry:build`
@@ -0,0 +1,74 @@
# Input Group Affixes
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a reusable input-affix composition layer so search icons, badges, and suffix actions stop
being page-level absolute-position wrappers and instead ship as a stable Cadence UI pattern.
## Scope
- In scope:
- add a public `InputGroup` companion pattern with prefix and suffix slots
- keep the existing `Input` API intact while letting it compose cleanly inside the new group
- update at least one real docs surface that currently hand-rolls affix layout
- add Storybook coverage and unit tests for the new slot and field wiring behavior
- Out of scope:
- redesigning `Field` or introducing a second label/help-text abstraction
- broad visual restyling of all text-entry surfaces
- migrating every existing search field in one pass
## Constraints
- Preserve the existing `Input` ref and prop contract for non-grouped usage.
- Follow the current `Field` state inheritance rules for disabled, invalid, readonly, and
required behavior.
- Expose stable `data-slot` hooks for the new affix anatomy.
- Keep the new pattern token-driven and visually aligned with the current input chrome.
## Affected Surfaces
- `docs/exec-plans/2026-03-25-input-group-affixes.md`
- `packages/ui/src/lib/contracts.ts`
- `packages/ui/src/components/input.tsx`
- `packages/ui/src/components/input-group.tsx`
- `packages/ui/src/components/input-group.variants.ts`
- `packages/ui/src/components/input-group.test.tsx`
- `packages/ui/src/components/data-table.tsx`
- `packages/ui/src/components/command.tsx`
- `packages/ui/src/components/command.test.tsx`
- `packages/ui/src/index.ts`
- `apps/docs/src/components/input-group.stories.tsx`
- `apps/docs/src/revenue-dashboard.stories.tsx`
- `registry/index.json`
## Plan
1. Add the execution plan and define the new input-affix pattern against the existing
`Input`/`Field` contract.
2. Implement `InputGroup` plus grouped-input behavior without regressing standalone `Input`.
3. Migrate the most obvious repeated search wrapper surfaces to the new composition layer.
4. Add stories, tests, and registry updates, then run the narrowest useful validation passes.
## Validation
- `pnpm --filter @ai-ui/ui test -- --run packages/ui/src/components/input-group.test.tsx packages/ui/src/components/input.test.tsx packages/ui/src/components/command.test.tsx`
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm harness:validate:docs`
- `pnpm registry:build`
## Orchestration Task Sketch
- `T1`: implement the input group component and integrate standalone input behavior
- `T2 -> T1`: migrate docs usage and command/data-table composition to the new slots
- `T3 -> T1`: add tests, stories, and registry updates
## Status Log
- `2026-03-25 14:29` Read the system-of-record files and confirmed the current `Input` contract has no affix composition layer.
- `2026-03-25 14:35` Chose a sibling `InputGroup` pattern over mutating `Input` into a wrapped root so the existing input API stays stable outside grouped usage.
- `2026-03-25 15:17` Implemented `InputGroup`, grouped input behavior, and the first consumer migrations in `CommandInput`, `DataTableSearch`, and the revenue dashboard story.
- `2026-03-25 15:24` Verified `pnpm --filter @ai-ui/ui test -- --run packages/ui/src/components/input-group.test.tsx packages/ui/src/components/input.test.tsx packages/ui/src/components/command.test.tsx packages/ui/src/components/data-table.test.tsx`, `pnpm --filter @ai-ui/ui typecheck`, `pnpm harness:validate:docs`, and `pnpm registry:build`.
@@ -0,0 +1,68 @@
# Layout Patterns Layer
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a dedicated `patterns` layer inside `@ai-ui/ui` for reusable page and shell structures that
sit above base components: `SidebarNav`, `PageHeader`, `AppShell`, and `PageFooter`.
## Scope
- In scope:
- create `packages/ui/src/patterns/`
- implement `SidebarNav`, `PageHeader`, `AppShell`, and `PageFooter`
- export the new patterns from `@ai-ui/ui`
- add Storybook docs under `Patterns/*`
- refactor the revenue dashboard scene to consume the new patterns where they fit
- add focused tests for the public slot and state contract
- Out of scope:
- splitting a second npm package for patterns
- adding router-aware or data-source-aware app shells
- replacing every existing layout composition across the repo in one slice
## Constraints
- Keep `components` as the lower layer and allow `patterns` to depend on `components`, not the reverse.
- Follow `DESIGN.md` and reuse the existing token and motion system instead of inventing a separate layout skin.
- Keep APIs compound and slot-oriented so different pages can restyle the same patterns.
- Use Storybook titles under `Patterns/*` so the review surface reflects the new layer clearly.
## Affected Surfaces
- `packages/ui/src/patterns`
- `packages/ui/src/index.ts`
- `apps/docs/src/patterns`
- `apps/docs/src/revenue-dashboard.stories.tsx`
- `docs/exec-plans`
## Plan
1. Create the new `patterns` directory and implement the four shared layout patterns with stable
slots and restrained variant surfaces.
2. Export the patterns from `@ai-ui/ui` without moving the existing base components.
3. Add docs stories under `Patterns/*` that explain when to use each pattern.
4. Refactor the revenue dashboard scene to consume `SidebarNav`, `PageHeader`, and `AppShell`, and
use `PageFooter` where it adds real value.
5. Add focused tests and run the narrowest useful validation suites.
## Validation
- `pnpm --filter @ai-ui/ui test -- sidebar-nav page-header page-footer app-shell`
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm build:docs`
## Orchestration Task Sketch
- `T1`: implement the new `patterns` layer and exports
- `T2 -> T1`: add docs stories for the four patterns
- `T3 -> T2`: refactor the revenue dashboard consumer and run focused validation
## Status Log
- `2026-03-25 16:48` started the patterns-layer slice after confirming the repo has component-internal headers and footers but no dedicated page-shell layer for shared layout structures
- `2026-03-25 17:06` implemented the new `packages/ui/src/patterns/` layer with `SidebarNav`, `PageHeader`, `PageFooter`, and `AppShell`, then exported the new public surface from `@ai-ui/ui`
- `2026-03-25 17:10` added Storybook docs under `Patterns/*` and refactored the revenue dashboard scene to consume the new shell and page patterns
- `2026-03-25 17:12` validated exact new pattern tests, workspace typecheck, and Storybook production build; the broader `pnpm --filter @ai-ui/ui test -- ...` entrypoint still pulls in unrelated in-flight `combobox` and `command` failures from concurrent work
@@ -0,0 +1,72 @@
# Segmented Control
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a compact `SegmentedControl` component to `@ai-ui/ui` for lightweight dashboard-style view
switching so consumers do not need to stretch `Tabs` into every small top-of-panel toggle.
## Scope
- In scope:
- add a new `SegmentedControl` component to `packages/ui`
- expose the component from the package entrypoint
- add unit coverage for controlled/uncontrolled behavior and stable contract hooks
- add Storybook docs that explain when to choose `SegmentedControl` instead of `Tabs`
- update the revenue dashboard story to use the new control for its contribution switcher
- refresh `registry/index.json` so source-copy consumers can install the new component
- Out of scope:
- redesigning the existing `Tabs` API
- replacing every current `Tabs` usage across docs
- adding icon-only, multi-select, or overflow handling variants in the first pass
## Constraints
- Keep the API narrower than `Tabs`; this should solve lightweight switching, not become another
generic navigation primitive.
- Reuse the current token and motion language from `DESIGN.md` instead of introducing a new visual
style.
- Preserve stable `data-slot` and `data-*` hooks for docs and tests.
- Do not add a new dependency if the existing Radix stack is sufficient.
## Affected Surfaces
- `docs/exec-plans/2026-03-25-segmented-control.md`
- `packages/ui/src/components/segmented-control.tsx`
- `packages/ui/src/components/segmented-control.variants.ts`
- `packages/ui/src/components/segmented-control.test.tsx`
- `packages/ui/src/index.ts`
- `apps/docs/src/components/segmented-control.stories.tsx`
- `apps/docs/src/revenue-dashboard.stories.tsx`
- `registry/index.json`
## Plan
1. Add the execution plan and confirm the public contract for a compact single-select control.
2. Implement `SegmentedControl` in `packages/ui` with stable slots, disabled state, and controlled
or uncontrolled value support.
3. Add Storybook docs that explain the intended usage boundary against `Tabs`.
4. Replace the revenue dashboard contribution switcher with `SegmentedControl` to prove the
dashboard-friendly use case.
5. Run targeted validation and refresh registry metadata.
## Validation
- `pnpm test -- --runInBand segmented-control tabs`
- `pnpm harness:validate:docs`
- `pnpm registry:build`
## Orchestration Task Sketch
- `T1`: implement `SegmentedControl` source, variants, and exports
- `T2 -> T1`: add docs stories and migrate the revenue dashboard example
- `T3 -> T1`: add tests and refresh registry metadata
## Status Log
- `2026-03-25 20:07` Read the system-of-record files and confirmed that `Tabs` is currently the only compact peer-switching primitive in the public surface.
- `2026-03-25 20:18` Started the segmented-control slice to cover lightweight dashboard toggles without expanding the `Tabs` API.
- `2026-03-25 23:32` Shipped the new `SegmentedControl`, migrated the revenue dashboard contribution switcher, refreshed `registry/index.json`, and cleared the existing `InputGroup` type blocker so build and docs validation could pass again.
@@ -0,0 +1,72 @@
# Sparkbar Primitive
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a dedicated `Sparkbar` micro-visual primitive to `@ai-ui/ui` so compact KPI cards and
dashboard tiles can render tiny bar-based trend summaries without hand-written DOM.
## Scope
- In scope:
- add a new `Sparkbar` component to `packages/ui`
- keep the API narrow and card-focused: small size, low configuration, embedded usage
- support simple bar highlighting for active ranges without turning the component into a full
charting surface
- add unit tests and Storybook docs for the public contract
- replace the hand-written sparkbar markup in `apps/docs/src/revenue-dashboard.stories.tsx`
and the related metric-card docs story
- Out of scope:
- introducing a full `Sparkline` API in the same slice
- adding axes, tooltips, interaction, or data transforms that belong to `Chart`
- expanding `Chart` itself to absorb micro-visual responsibilities
- broader dashboard contract cleanup outside the bar micro-vis use cases
## Constraints
- Follow `DESIGN.md` and keep the visual language tonal, rounded, and quiet enough for card media.
- Preserve a stable slot and `data-*` contract so docs and tests can target the primitive.
- Keep the public API additive and intentionally smaller than `Chart`.
- Avoid rewriting unrelated dirty-worktree changes while touching shared files like docs stories and
package exports.
## Affected Surfaces
- `docs/exec-plans/2026-03-25-sparkbar-primitive.md`
- `packages/ui/src/components/sparkbar.tsx`
- `packages/ui/src/components/sparkbar.variants.ts`
- `packages/ui/src/components/sparkbar.test.tsx`
- `packages/ui/src/index.ts`
- `packages/ui/src/skins.css`
- `apps/docs/src/components/sparkbar.stories.tsx`
- `apps/docs/src/components/metric-card.stories.tsx`
- `apps/docs/src/revenue-dashboard.stories.tsx`
- `registry/index.json`
## Plan
1. Define a narrow `Sparkbar` API for embedded numeric bar trends and active-range emphasis.
2. Implement the component with stable slots, tone/variant styling, and decorative-by-default
accessibility behavior.
3. Add Storybook stories that explain when to use `Sparkbar` instead of `Chart`.
4. Replace the existing hand-written bar maps in docs consumers with the new primitive.
5. Run focused package and docs validation, then record any remaining gaps.
## Validation
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm --filter @ai-ui/ui exec vitest run packages/ui/src/components/sparkbar.test.tsx --config ../../vitest.config.ts`
- `pnpm exec eslint apps/docs/src/components/sparkbar.stories.tsx apps/docs/src/components/metric-card.stories.tsx apps/docs/src/revenue-dashboard.stories.tsx packages/ui/src/components/sparkbar.tsx packages/ui/src/components/sparkbar.variants.ts packages/ui/src/components/sparkbar.test.tsx packages/ui/src/index.ts`
- `pnpm harness:validate:docs`
- `pnpm registry:build`
## Status Log
- `2026-03-25 21:15` Read the system-of-record files and confirmed the repo currently has a full `Chart` pattern but no dedicated micro bar-trend primitive.
- `2026-03-25 21:22` Scoped the new component as `Sparkbar`: low-config, non-interactive, card-embedded, and explicitly separate from `Chart`.
- `2026-03-25 23:18` Implemented `Sparkbar`, tokenized its size/tone/variant styling, exported it from `@ai-ui/ui`, and added unit coverage for slots, emphasis, and accessibility behavior.
- `2026-03-25 23:28` Added dedicated Storybook docs and migrated the handwritten spark bars in the revenue dashboard and metric-card stories to the new primitive.
- `2026-03-25 23:34` Verified `pnpm --filter @ai-ui/ui typecheck`, targeted Sparkbar Vitest coverage, targeted ESLint, `pnpm harness:validate:docs`, and `pnpm registry:build`.
@@ -0,0 +1,65 @@
# Stat And Metric Cards
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add two dashboard-oriented composition components to `@ai-ui/ui`: a compact `StatCard`
for the common label/value/delta/description KPI pattern, and a richer `MetricCard`
that extends the same pattern with media, footer, and action regions for analytics
panels.
## Scope
- In scope:
- add `StatCard` and `MetricCard` component source, variants, exports, tests, and docs
- expose stable slot and state metadata consistent with the repo contract
- refactor the new revenue dashboard scene to consume the components where they fit
- Out of scope:
- introducing a full dashboard layout system
- replacing all existing card-based compositions across the repo
- expanding the chart system beyond what already exists
## Constraints
- Follow the active Material-inspired design direction in `DESIGN.md`.
- Keep the API small and slot-oriented rather than introducing a single oversized props surface.
- Reuse existing card tokens and motion recipes instead of creating a parallel styling layer.
- Preserve enough flexibility that richer panels can still compose custom chart and footer content.
## Affected Surfaces
- `packages/ui/src/components`
- `packages/ui/src/index.ts`
- `apps/docs/src/components`
- `apps/docs/src/revenue-dashboard.stories.tsx`
- `docs/exec-plans`
## Plan
1. Implement `StatCard` as a compact KPI card with semantic slots for eyebrow, label, value, delta, and description.
2. Implement `MetricCard` on the same visual and slot contract, adding media, footer, and actions regions plus layout variants.
3. Add focused tests and Storybook stories that document the standard usage, anatomy, and review guidance.
4. Refactor the revenue dashboard scene to consume the new components for representative panels.
5. Run focused validation and record any unrelated repository issues that remain.
## Validation
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm --filter @ai-ui/ui test`
- `pnpm build:docs`
## Orchestration Task Sketch
- `T1`: implement `StatCard` and `MetricCard` source plus exports
- `T2 -> T1`: add stories/tests and refactor the revenue dashboard scene
- `T3 -> T2`: run focused validation and document residual issues
## Status Log
- `2026-03-25 16:16` started the stat/metric card slice after confirming the current dashboard scene still relies on repeated KPI glue code
- `2026-03-25 16:27` implemented `StatCard` and `MetricCard`, exported them from `@ai-ui/ui`, added tests and Storybook stories, and refactored representative revenue-dashboard panels onto the new components
- `2026-03-25 16:31` validated `pnpm --filter @ai-ui/ui typecheck`, `pnpm --filter @ai-ui/ui test`, `pnpm build`, and `pnpm build:docs`
- `2026-03-25 16:33` noted that the running Storybook dev session still carries unrelated development noise from other in-flight docs slices (`progress.stories.tsx` index warnings and an `InputGroup` runtime export mismatch on the dashboard iframe), but the package build and Storybook production build both pass
@@ -0,0 +1,59 @@
# Two-Factor Setup Pattern
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a new Storybook pattern for a two-factor setup flow that captures the structure of the
reference UI while staying inside Cadence UI's lighter Material-tonal design direction and
reusing the existing component set instead of introducing a new public package component.
## Scope
- In scope:
- add a new docs pattern under `apps/docs/src/patterns/`
- compose the scene with existing components such as `Badge`, `Button`, `Card`, `Field`, `Input`,
and `InputGroup`
- document why this belongs in `Patterns` instead of `Components`
- Out of scope:
- adding a new public `packages/ui` export
- introducing a dedicated OTP primitive or authentication package
- wiring real QR generation, API calls, or clipboard guarantees
## Constraints
- Keep the visual direction aligned with `DESIGN.md`: tonal, light, rounded, and calm.
- Avoid introducing a black, neon, or high-contrast security-console aesthetic.
- Reuse existing components wherever practical and keep one-off styling local to the story.
- Do not disturb unrelated in-flight work in the dirty worktree.
## Affected Surfaces
- `apps/docs/src/patterns`
- `docs/exec-plans`
## Plan
1. Add the execution plan and confirm this slice should live in `Patterns`.
2. Implement a new `Patterns/TwoFactorSetup` story that composes existing UI primitives into a
modal-ready 2FA setup scene.
3. Add anatomy and accessibility-oriented review stories so placement and usage are explicit.
4. Run focused docs validation and record the result.
## Validation
- `pnpm build:docs`
## Orchestration Task Sketch
- `T1`: add the docs-only two-factor setup pattern story
- `T2 -> T1`: run focused docs validation and record outcomes
## Status Log
- `2026-03-25 22:10` started the slice after confirming the reference is better treated as a composed auth pattern than as a new base component or dialog variant
- `2026-03-25 22:18` added `Patterns/TwoFactorSetup` as a docs-only pattern story built from existing components with a lighter tonal treatment instead of the reference's dark security-console styling
- `2026-03-25 22:20` validated the new story with `pnpm build:docs`
- `2026-03-25 19:02` migrated the scene's split layout and accessibility review layout onto the shared `Row` / `Col` grid primitives so the pattern no longer depends on local fixed desktop column math
@@ -0,0 +1,66 @@
# Value Field Component
- Status: `in_progress`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a reusable `ValueField` base component for single-line, read-only value presentation so product
flows do not have to misuse `Input` for non-editable display values such as backup codes, reference
ids, tokens, or generated labels.
## Scope
- In scope:
- add a new public `ValueField` component to `packages/ui`
- support a minimal composable surface for value display plus optional prefix/suffix content
- integrate with `Field` context for state and description wiring
- document the component in Storybook
- cover key behavior with unit tests
- use the new component in the docs-only two-factor setup pattern
- Out of scope:
- multiline or rich-text display values
- formatted masking, async copy state, or built-in clipboard APIs
- replacing every read-only input in the repo
## Constraints
- Keep the component token-first and aligned with the existing input/card/panel visual language.
- Do not create a second form-field system parallel to `Field`.
- Keep the public API small and composable.
- Prefer stable slot names and `data-*` state exposure over one-off booleans.
## Affected Surfaces
- `packages/ui/src/components`
- `packages/ui/src/index.ts`
- `packages/ui/src/lib/contracts.ts`
- `apps/docs/src/components`
- `apps/docs/src/patterns`
- `docs/exec-plans`
## Plan
1. Add the execution plan and confirm the API should be a small read-only display primitive rather
than a typography helper.
2. Implement `ValueField` in `packages/ui` with stable slots for root/value/prefix/suffix and
Field-context aware ids and state attributes.
3. Add Storybook stories and update the two-factor setup pattern to use `ValueField` for the manual
backup code.
4. Add unit coverage and run targeted validation for component and docs surfaces.
## Validation
- `pnpm build:docs`
- targeted component test run for `ValueField`
## Orchestration Task Sketch
- `T1`: implement the `ValueField` component and exports
- `T2 -> T1`: add docs stories, update the two-factor pattern, and validate
## Status Log
- `2026-03-25 23:40` started after confirming the repo exposes read-only input styling but no
dedicated single-line value display component
@@ -0,0 +1,65 @@
# Workspace Toolbar Pattern
- Status: `completed`
- Owner: `codex`
- Date: `2026-03-25`
## Goal
Add a reusable `WorkspaceToolbar` pattern above the base component layer so workspace and desk-style
screens can share one stable contract for search, filters, status chips, and action groups instead
of hand-rolling a new top control row in each story or scene.
## Scope
- In scope:
- add a new `WorkspaceToolbar` pattern under `packages/ui/src/patterns/`
- export the new pattern from `@ai-ui/ui`
- add Storybook docs under `Patterns/WorkspaceToolbar`
- refactor the revenue dashboard scene to consume the new pattern
- add focused tests for the slot and variant contract
- Out of scope:
- moving `DataTable` internal toolbar logic into the patterns layer
- adding router-aware behavior, sticky behavior, or data-source behavior
- introducing a second page-header-like title system inside the toolbar
## Constraints
- Keep the API slot-oriented and composable instead of baking in search or filter behavior.
- Reuse the existing token and motion system from `DESIGN.md`.
- Keep the public variant surface restrained.
- Do not disturb unrelated in-flight work in the dirty worktree.
## Affected Surfaces
- `packages/ui/src/patterns`
- `packages/ui/src/index.ts`
- `apps/docs/src/patterns`
- `apps/docs/src/revenue-dashboard.stories.tsx`
- `docs/exec-plans`
## Plan
1. Add the new pattern implementation, variants, and focused tests in `packages/ui/src/patterns/`.
2. Export the pattern from `@ai-ui/ui` and add Storybook docs under `Patterns/*`.
3. Refactor the revenue dashboard toolbar composition to consume the shared pattern.
4. Run focused validation and record any skipped or blocked checks.
## Validation
- `pnpm --filter @ai-ui/ui test -- workspace-toolbar`
- `pnpm --filter @ai-ui/ui typecheck`
- `pnpm build:docs`
## Orchestration Task Sketch
- `T1`: implement the new pattern and public exports
- `T2 -> T1`: add docs stories and refactor the dashboard consumer
- `T3 -> T2`: run focused validation and record outcomes
## Status Log
- `2026-03-25 19:13` started the workspace-toolbar slice after confirming the current patterns layer stops at shell and page framing, while the revenue dashboard still hand-rolls a workspace control row
- `2026-03-25 19:20` implemented `WorkspaceToolbar` with slot-based search, filters, status, and actions regions, then exported the new public pattern from `@ai-ui/ui`
- `2026-03-25 19:24` added `Patterns/WorkspaceToolbar` Storybook docs and refactored the revenue dashboard scene to consume the shared toolbar pattern
- `2026-03-25 19:26` validated the change with `pnpm --filter @ai-ui/ui test -- workspace-toolbar`, `pnpm --filter @ai-ui/ui typecheck`, and `pnpm build:docs`