Skip to content

Extract @codra/ui, the reusable component library #75

Description

@devarshishimpi

Why

The client already has a real design system underneath the app: ui-* surface tokens and primitives in src/client/components/ui (button, input, select, switch, badge, alert, text, layer-card, confirm-dialog), generic pieces in src/client/components/shared (skeleton, empty-state, section-card, copy-button, jobs-table, bar-sparkline), motion helpers in src/client/components/motion, and cross-cutting utilities in src/client/lib (theme, utils, highlight, file-tree, ease, timezone). None of it is separable from the app today. This issue has no dependency on the server-side extraction issues and can be done at any point.

Scope

  • Create packages/ui/src holding the primitives, the generic shared components, the motion helpers, the token/theme layer from src/client/app.css and src/client/lib/theme.tsx, and the presentational utilities.
  • Move feature components (src/client/components/features) and pages (src/client/pages) to apps/dashboard, which depends on packages/ui.
  • Enforce the boundary with the eslint import rule from the scaffolding issue: nothing in packages/ui may import from apps/dashboard, reference a route path, call src/client/lib/api.ts, or know about domain entities. Components take props.
  • Split the components that currently straddle the line, jobs-table.tsx, page-header-actions.tsx and chart-primitives.tsx, into a generic primitive in packages/ui plus a domain-aware wrapper left in apps/dashboard.
  • Keep recharts/motion/lucide as peer dependencies of packages/ui so consumers control versions, and confirm the manual chunking in vite.config.ts (now apps/dashboard/vite.config.ts) still splits vendors correctly.
  • Every moved component must render correctly in both light and dark theme, using tokens rather than literal colors.

Acceptance criteria

  • packages/ui builds and typechecks with no dependency on app code, routing, or the API client.
  • The dashboard is visually unchanged; client bundle size does not regress.
  • A lint rule fails the build on an app-layer import inside packages/ui.

Non-goals

Redesigning anything. Visual output should be pixel-identical to main.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions