524 lines
11 KiB
Markdown
524 lines
11 KiB
Markdown
# Cadence UI Roadmap
|
|
|
|
## Goal
|
|
|
|
Build a long-term maintainable component system inspired by `shadcn/ui`, but owned by this repo:
|
|
|
|
- keep the `Radix + Tailwind + source-owned components` model
|
|
- replace default styling with our own tokens and component rules
|
|
- make motion a first-class system layer, not ad hoc transitions
|
|
- support theming, accessibility, testing, and internal registry distribution
|
|
|
|
## Status Snapshot
|
|
|
|
This document began as the build-out plan for the system. The current repo has already
|
|
completed most of that baseline work:
|
|
|
|
- phases 0 through 4 are effectively in place: workspace, tokens, authoring contract, core components, Storybook docs, and baseline tests
|
|
- phase 5 has shipped its first advanced-pattern slice with `DataTable`, alongside `Command`, `Combobox`, `Sheet`, and `EmptyState`
|
|
- phase 6 now covers package-first release automation, fixed-version package publishing, and the optional source-copy registry flow
|
|
|
|
The next work is mostly hardening and distribution:
|
|
|
|
- keep the registry metadata and consumer smoke flow reliable
|
|
- keep package publish validation and tag automation reliable
|
|
- expand advanced patterns only where real product usage justifies them
|
|
|
|
## Product Principles
|
|
|
|
1. Source owned
|
|
Components live in our codebase and are modified directly.
|
|
2. Token first
|
|
Visual and motion decisions are defined as tokens before being embedded in components.
|
|
3. Component contract over component count
|
|
Stable API patterns matter more than shipping many components quickly.
|
|
4. Accessibility by default
|
|
Keyboard, focus, ARIA, and reduced motion are baseline requirements.
|
|
5. Motion with purpose
|
|
Animation must communicate state, feedback, and hierarchy.
|
|
6. Incremental adoption
|
|
Start from a small core and expand only after patterns are stable.
|
|
|
|
## Recommended Stack
|
|
|
|
### Core
|
|
|
|
- `React`
|
|
- `TypeScript`
|
|
- `pnpm workspace`
|
|
- `Tailwind CSS`
|
|
- `CSS variables`
|
|
- `Radix UI`
|
|
- `class-variance-authority`
|
|
- `clsx`
|
|
- `tailwind-merge`
|
|
|
|
### Motion
|
|
|
|
- CSS transitions and keyframes for default interactions
|
|
- `motion` or `framer-motion` for advanced choreography only
|
|
- `prefers-reduced-motion` support from day one
|
|
|
|
### Docs and DX
|
|
|
|
- `Storybook`
|
|
- `Lucide React`
|
|
- `react-hook-form`
|
|
- `zod`
|
|
|
|
### Quality and Release
|
|
|
|
- `Vitest`
|
|
- `@testing-library/react`
|
|
- `Playwright`
|
|
- `axe-core` or `jest-axe`
|
|
- `tsup`
|
|
- `Changesets`
|
|
|
|
## Target Repository Structure
|
|
|
|
```txt
|
|
apps/
|
|
docs/ # Storybook or docs app
|
|
packages/
|
|
ui/ # component source
|
|
tokens/ # design + motion tokens
|
|
icons/ # optional icon wrappers
|
|
config/ # shared ts/eslint/tailwind config, optional
|
|
registry/ # internal source-copy registry
|
|
```
|
|
|
|
### `packages/ui` structure
|
|
|
|
```txt
|
|
src/
|
|
lib/
|
|
cn.ts
|
|
cva.ts
|
|
motion.ts
|
|
styles/
|
|
base.css
|
|
tokens.css
|
|
motion.css
|
|
primitives/
|
|
components/
|
|
button/
|
|
input/
|
|
dialog/
|
|
dropdown-menu/
|
|
tabs/
|
|
toast/
|
|
patterns/
|
|
form/
|
|
data-table/
|
|
```
|
|
|
|
## System Layers
|
|
|
|
### 1. Tokens
|
|
|
|
Define semantic tokens instead of hardcoded visual values.
|
|
|
|
Visual token groups:
|
|
|
|
- colors
|
|
- typography
|
|
- radius
|
|
- shadow
|
|
- border
|
|
- spacing when needed beyond Tailwind defaults
|
|
|
|
Motion token groups:
|
|
|
|
- `--dur-fast`
|
|
- `--dur-base`
|
|
- `--dur-slow`
|
|
- `--ease-standard`
|
|
- `--ease-emphasized`
|
|
- `--distance-xs`
|
|
- `--distance-sm`
|
|
- `--scale-press`
|
|
|
|
### 2. Primitives
|
|
|
|
Use `Radix UI` as the accessibility and interaction base where appropriate.
|
|
|
|
Examples:
|
|
|
|
- dialog
|
|
- popover
|
|
- dropdown-menu
|
|
- tabs
|
|
- toast
|
|
- checkbox
|
|
- radio-group
|
|
- switch
|
|
|
|
### 3. Motion Recipes
|
|
|
|
Reusable motion patterns that components consume instead of redefining animation logic.
|
|
|
|
Initial recipe set:
|
|
|
|
- `fade-in`
|
|
- `fade-out`
|
|
- `slide-up-sm`
|
|
- `slide-down-sm`
|
|
- `overlay-enter`
|
|
- `overlay-exit`
|
|
- `press-feedback`
|
|
- `focus-ring-transition`
|
|
- `accordion-expand`
|
|
- `toast-enter`
|
|
- `toast-exit`
|
|
|
|
### 4. Components
|
|
|
|
Components compose tokens, primitives, and motion recipes into a stable public API.
|
|
|
|
## Component Contract
|
|
|
|
All components should follow a consistent contract where relevant:
|
|
|
|
- support `className`
|
|
- forward `ref`
|
|
- use `variant` only where it adds actual semantic value
|
|
- use `size` only where it is meaningful
|
|
- support `asChild` for composable primitives
|
|
- expose controlled and uncontrolled APIs when appropriate
|
|
- expose stable states through attributes such as `data-state`, `data-disabled`, and `data-invalid`
|
|
- include loading, disabled, error, and focus behaviors where applicable
|
|
|
|
## Design Rules
|
|
|
|
### Keep from shadcn
|
|
|
|
- source-distributed component ownership model
|
|
- composable React API patterns
|
|
- `Radix + Tailwind + CVA` implementation style
|
|
- pragmatic developer experience
|
|
|
|
### Replace from shadcn
|
|
|
|
- default visual tokens
|
|
- default component variants
|
|
- default color and radius assumptions
|
|
- default animation choices
|
|
- package and registry conventions when our patterns stabilize
|
|
|
|
## Motion Rules
|
|
|
|
Default timing guidance:
|
|
|
|
- press feedback: `100-140ms`
|
|
- hover and focus: `160-200ms`
|
|
- popover, dropdown, tooltip: `180-240ms`
|
|
- dialog and drawer: `220-320ms`
|
|
- section entrance: `320-480ms`
|
|
- exits should generally be faster than entrances
|
|
|
|
Implementation rules:
|
|
|
|
- prefer animating `transform` and `opacity`
|
|
- avoid `transition-all`
|
|
- avoid animating `width`, `height`, `top`, `left`, `padding`, `margin`
|
|
- use `data-state` driven animation where possible
|
|
- support `prefers-reduced-motion`
|
|
- use JS animation only for interactions CSS cannot express cleanly
|
|
|
|
## Delivery Phases
|
|
|
|
## Phase 0: Foundation Setup
|
|
|
|
Objective:
|
|
Create the monorepo foundation and install the baseline tooling.
|
|
|
|
Deliverables:
|
|
|
|
- `pnpm workspace`
|
|
- root `package.json`
|
|
- `packages/ui`
|
|
- `packages/tokens`
|
|
- `apps/docs`
|
|
- Tailwind, TypeScript, ESLint, and build setup
|
|
|
|
Exit criteria:
|
|
|
|
- workspace installs cleanly
|
|
- docs app boots
|
|
- `packages/ui` builds
|
|
|
|
## Phase 1: Token System
|
|
|
|
Objective:
|
|
Define the first stable visual and motion token layer.
|
|
|
|
Deliverables:
|
|
|
|
- `tokens.css`
|
|
- `motion.css`
|
|
- semantic color scale
|
|
- radius, shadow, border, typography tokens
|
|
- motion duration, easing, distance, and scale tokens
|
|
- one Morandi theme baseline
|
|
- one optional brand theme scaffold
|
|
|
|
Exit criteria:
|
|
|
|
- components can consume tokens without hardcoded brand values
|
|
- theme switching works at token level
|
|
- reduced motion rules exist globally
|
|
|
|
## Phase 2: Core Utilities and Contracts
|
|
|
|
Objective:
|
|
Standardize the implementation patterns every component will use.
|
|
|
|
Deliverables:
|
|
|
|
- `cn.ts`
|
|
- `cva.ts` conventions
|
|
- shared component authoring guidelines
|
|
- state naming and slot naming conventions
|
|
- motion helper conventions
|
|
|
|
Exit criteria:
|
|
|
|
- new components can follow one repeatable implementation pattern
|
|
- API expectations are documented
|
|
|
|
## Phase 3: Core Component Set
|
|
|
|
Objective:
|
|
Ship the first stable component layer.
|
|
|
|
Priority components:
|
|
|
|
- `Button`
|
|
- `Input`
|
|
- `Textarea`
|
|
- `Checkbox`
|
|
- `Radio Group`
|
|
- `Switch`
|
|
- `Select`
|
|
- `Dialog`
|
|
- `Dropdown Menu`
|
|
- `Tabs`
|
|
- `Toast`
|
|
- `Form`
|
|
|
|
Exit criteria:
|
|
|
|
- all core components support tokens and motion recipes
|
|
- all core components have docs stories
|
|
- all core components have baseline tests
|
|
|
|
## Phase 4: Documentation and QA
|
|
|
|
Objective:
|
|
Make the system safe to use and safe to evolve.
|
|
|
|
Deliverables:
|
|
|
|
- Storybook stories for all component states
|
|
- accessibility checks
|
|
- interaction tests
|
|
- visual review process
|
|
- contribution guide for new components
|
|
|
|
Exit criteria:
|
|
|
|
- docs cover variants, sizes, states, themes, and reduced motion
|
|
- core components pass accessibility and interaction checks
|
|
|
|
## Phase 5: Advanced Patterns
|
|
|
|
Status:
|
|
Baseline shipped.
|
|
|
|
Objective:
|
|
Build higher-level patterns only after the base layer is stable.
|
|
|
|
Candidate patterns:
|
|
|
|
- `Form`
|
|
- `Data Table`
|
|
- `Command`
|
|
- `Combobox`
|
|
- `Date Picker`
|
|
- `Drawer`
|
|
- `Sheet`
|
|
- `Empty State`
|
|
|
|
Current shipped patterns:
|
|
|
|
- `Form`
|
|
- `Data Table`
|
|
- `Command`
|
|
- `Combobox`
|
|
- `Sheet`
|
|
- `Empty State`
|
|
|
|
Exit criteria:
|
|
|
|
- patterns reuse existing component contracts
|
|
- no pattern introduces a competing API style
|
|
|
|
## Phase 6: Internal Registry and Distribution
|
|
|
|
Status:
|
|
Package-first publishing and optional source-copy distribution are both in place.
|
|
|
|
Objective:
|
|
Create an internal distribution model similar to `shadcn`, but based on our own rules.
|
|
|
|
Deliverables:
|
|
|
|
- internal registry format
|
|
- code generation or copy-in workflow
|
|
- documentation for install and upgrade paths
|
|
- versioning and release process
|
|
|
|
Delivered so far:
|
|
|
|
- fixed-version package release pair for `@ai-ui/ui` and `@ai-ui/tokens`
|
|
- package consumer smoke validation
|
|
- tag-driven publish workflow
|
|
- generated `registry/index.json`
|
|
- local `pnpm registry:install` copy-in workflow
|
|
- `pnpm test:registry:consumer` validation
|
|
- Changesets status checks and version PR automation
|
|
|
|
Remaining follow-up:
|
|
|
|
- package registry operational hardening
|
|
- any automation beyond source-copy installs
|
|
|
|
Exit criteria:
|
|
|
|
- package consumers can install the published packages
|
|
- source-copy consumers can pull components from our registry
|
|
- upgrades are documented and reproducible
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit and Interaction
|
|
|
|
- `Vitest`
|
|
- `@testing-library/react`
|
|
- state and variant coverage
|
|
- controlled and uncontrolled behavior coverage
|
|
|
|
### Accessibility
|
|
|
|
- `axe-core` or `jest-axe`
|
|
- keyboard and focus-path checks
|
|
- reduced motion validation
|
|
|
|
### End-to-End
|
|
|
|
- `Playwright`
|
|
- open and close behavior
|
|
- keyboard navigation
|
|
- form submission flows
|
|
|
|
## Documentation Requirements
|
|
|
|
Every core component should document:
|
|
|
|
- purpose
|
|
- anatomy
|
|
- variants
|
|
- sizes
|
|
- states
|
|
- accessibility notes
|
|
- motion behavior
|
|
- reduced motion fallback
|
|
- example usage
|
|
|
|
## Risks to Manage
|
|
|
|
- over-customizing too early before contracts stabilize
|
|
- building too many components before token patterns settle
|
|
- letting business code create parallel component wrappers
|
|
- tying all animation to a JS library unnecessarily
|
|
- skipping docs and tests until later
|
|
|
|
## Initial Execution Plan
|
|
|
|
### Sprint 1
|
|
|
|
Goal:
|
|
Set up the workspace and foundation.
|
|
|
|
Tasks:
|
|
|
|
- initialize `pnpm workspace`
|
|
- create `apps/docs`
|
|
- create `packages/ui`
|
|
- create `packages/tokens`
|
|
- add Tailwind and TypeScript setup
|
|
- add Storybook
|
|
|
|
### Sprint 2
|
|
|
|
Goal:
|
|
Lock the first token layer and first motion layer.
|
|
|
|
Tasks:
|
|
|
|
- create `tokens.css`
|
|
- create `motion.css`
|
|
- define base semantic palette
|
|
- define duration and easing tokens
|
|
- add global reduced motion rules
|
|
|
|
### Sprint 3
|
|
|
|
Goal:
|
|
Ship the first reference components.
|
|
|
|
Tasks:
|
|
|
|
- implement `Button`
|
|
- implement `Input`
|
|
- implement `Dialog`
|
|
- add stories
|
|
- add tests
|
|
|
|
### Sprint 4
|
|
|
|
Goal:
|
|
Expand the core set using the same contract.
|
|
|
|
Tasks:
|
|
|
|
- implement `Dropdown Menu`
|
|
- implement `Tabs`
|
|
- implement `Toast`
|
|
- validate API consistency
|
|
|
|
## Definition of Done
|
|
|
|
A component is considered done only when:
|
|
|
|
- implementation is in `packages/ui`
|
|
- tokens are used instead of hardcoded presentation values
|
|
- motion follows shared recipes or shared timing rules
|
|
- documentation exists
|
|
- tests exist
|
|
- accessibility behavior is validated
|
|
- reduced motion behavior is defined
|
|
|
|
## First Build Target
|
|
|
|
The first meaningful milestone is:
|
|
|
|
- monorepo running
|
|
- tokens and motion tokens defined
|
|
- `Button`, `Input`, and `Dialog` shipped
|
|
- Storybook stories available
|
|
- baseline tests passing
|
|
|
|
This is the point where the system stops being an idea and becomes a reusable foundation.
|