livepeer / livepeer/design-system
Epic: Stitches → Tailwind v4 + CVA migration to v2.0.0
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 6
- Forks
- 6
- PR merge metrics
- No merged PRs in 30d
Description
Goal
Align @livepeer/design-system with the Livepeer website's visual language so Explorer (and the 2 other planned consumers) adopt the same look and feel using the same tokens, utility classes, and tooling. Migrate from Stitches (deprecated/unmaintained) to Tailwind CSS v4 + Radix + CVA, landing as v2.0.0.
Why
- Brand alignment — Explorer needs to match the new Livepeer website. The website is built on pure Tailwind v4 with a single
@themetoken block (app/globals.css). Sharing that token block makes Explorer brand-aligned by construction, no per-component restyling. - AI / designer ergonomics — Tailwind is the industry-standard styling vocabulary. Designer can copy website classes directly into Explorer; AI tools (Copilot/Cursor/Claude) generate Tailwind fluently. Stitches forces a translation step that breaks both flows.
- Stitches is unmaintained — no active development since 2022-10, growing security debt
- Stuck on TS 4.7 — TypeScript 5+ is blocked by Stitches'
$$PropertyValuedeclaration-emit bug (TS4118); only path forward is removing Stitches - Consumer impact — Livepeer Explorer (and up to 2 more planned consumers) need a stable, modern design-system
Release sequence
| Version | Contents | Breaking? |
|---|---|---|
| v1.1.2 | ✅ Published 2026-04-11. Aligns Button to the published 1.1.0 tarball behavior (restores subdued primary / neutral / color-loop + missing transparentWhite / transparentBlack variants). |
No (behavior patch; matches what Explorer already runs) |
| v1.2.0 | ✅ Published 2026-05-04. Infrastructure modernized (pnpm, tsup, React 18 peer dep, .nvmrc, Tailwind v4 + CVA bridge). TS stays at 4.7 — TS 5+ blocked by Stitches' TS4118 incompatibility. |
No (minor, additive) |
| v2.0.0 | Stitches removed, all components on Tailwind + CVA + Radix, TypeScript 5.9+, theme tokens unified with livepeer/website. Variant prop names preserved — migration is a styling translation, not an API rename. | Yes (major — Stitches API removed) |
Infrastructure phase (pre-Tailwind) → v1.2.0 ✅
- Upgrade CI to Node 20 and actions v4 — #153
- Document local consumer testing workflow with yalc — #154
- Align
components/Button.tsxto the published 1.1.0 tarball behavior — #158 - Publish v1.1.2 to npm — 2026-04-11
- Explorer consumer PR: bump to v1.1.2 — livepeer/explorer#622 (merged)
- Gitignore yalc artifacts — #159
- Migrate yarn → pnpm + add
.nvmrcwith Node version pin +enginesfield — #160 - Upgrade React 17 → 18 peer dep — #161
- Swap rollup → tsup + remove
.npmrcshamefully-hoist+ renametsconfig-rollup.json→tsconfig.build.json— #162 - Set up Tailwind v4 + CVA alongside existing Stitches (bridge) — #163
- Remove unused
@radix-ui/react-toggle-button@0.0.6zombie dep blockingnp'snpm install --engine-strictstep — #165 - Publish v1.2.0 to npm — 2026-05-04
- Explorer consumer PR: bump to v1.2.0 — livepeer/explorer#650
Note: TypeScript 4.7 → 5.x is intentionally deferred to v2.0.0. Stitches'
$$PropertyValuesymbol cannot be serialized by TS 5's declaration emitter (error TS4118). Since Stitches is unmaintained, there is no upstream fix — the only path to TS 5+ is removing Stitches entirely, which is a breaking change scoped for v2.0.0.
Token alignment with livepeer/website → v2.0.0
The website's app/globals.css @theme block defines the canonical brand: green/blue/dark color scale, Favorit Pro typography, utility classes (tile-bg, divider-gradient, text-gradient, image-mask-flow). v2.0.0 adopts this verbatim as design-system's source of truth.
- Copy website's
@themeblock (color tokens + font tokens) into design-system's Tailwind config - Port website utility classes (
tile-bg,divider-gradient,text-gradient) into design-system as exported utilities - Wire up Favorit Pro font loading (consumers may need to mirror the website's font setup or pull from a shared package)
- Add a contributor note (or a small CI check) ensuring website + design-system token blocks stay in sync — single source of truth
Component migration phase (Stitches → Tailwind + CVA) → v2.0.0
Each batch is a standalone PR. Strategy: replace Stitches styled() with CVA recipes + Tailwind classes, keep Radix wrappers, preserve existing variant prop names (primary, neutral, red, transparentWhite, etc.) so Explorer's call sites need styling translation only — not API find-replace.
Suggested sequence (foundation → composition):
- Visual primitives (Box, Flex, Grid, Container, Section, Separator, Card) — start here; unblocks layout for every other batch
- Typography (Heading, Text, Code, Link, Blockquote, Paragraph)
- Button — restyle internals only, preserve all current variant names
- Form primitives (Input, Textarea, Label, Checkbox, Radio, Switch, Select, Slider)
- Overlay components (Dialog, AlertDialog, Popover, Tooltip, HoverCard, DropdownMenu, ContextMenu) — keep Radix wrappers
- Data display (Avatar, Badge, Table, Progress, AspectRatio)
- Navigation (Tabs, Accordion, ScrollArea, Menu)
- Misc (Toast, Skeleton, Collapsible)
v2.0.0 release
- Remove Stitches dependency entirely
- Upgrade TypeScript 4.7 → 5.9+ (unblocked by Stitches removal — TS4118 no longer applies)
- Upgrade React 18 → 19 peer dep (optional — 18 is fine for broader compat)
- Update public API exports (drop
styled,css,getCssText,globalCss,keyframes,config; addcn()and re-export theme tokens) - Migration guide for consumers — translation table for
css={{...}}→className="...", plus token name reference - Update LICENSE copyright to "Livepeer Foundation"
- Publish v2.0.0
- Consumer upgrade PR: Livepeer Explorer → v2.0.0
Consumer impact
- v1.1.2 ✅ — Button behavior aligned to the published 1.1.0 tarball. Zero consumer code changes.
- v1.2.0 ✅ — additive infra modernization (pnpm, tsup, React 18 peer dep, Tailwind bridge). Consumers upgrade safely. TS stays at 4.7.
- v2.0.0 — breaking: Stitches API removed (
styled/css/getCssText/etc.). Consumer apps need a translation pass to convertcss={{...}}props toclassName="...". Variant prop names preserved (noprimary→secondaryrename) — the migration is styling-only, not API churn. Visual outcome: Explorer matches the website's brand language out of the box.
Plan revision history
- 2026-04-04 — initial epic. Plan included shadcn-aligned variant rename track.
- 2026-05-04 — scoped down. Goal clarified as alignment with livepeer/website, not shadcn convention adoption. Dropped variant-rename track (
primary→secondary,neutral→outline,red→destructive) and$primary→$foregroundtoken rename — neither serves the website-alignment goal, and both inflate consumer migration cost. Replaced with explicit "copy the website's@themeblock" track.
References
- livepeer/website source of truth: https://github.com/livepeer/website (Next 15 + Tailwind v4 + Favorit Pro). The
@themeblock inapp/globals.cssis the canonical brand token set v2.0.0 mirrors. - TS 5 blocker:
@stitches/reactuses$$PropertyValue(symbol-indexed type) in CSS property value inference. TypeScript 5.0+ refuses to serialize this symbol in declaration emit (error TS4118). Stitches is unmaintained (last release 2022-10) — no upstream fix possible. Verified 2026-04-12: both TS 5.4.5 and 5.9.3 fail with TS4118 oncomponents/Accordion.tsxduring declaration emit. Only path to TS 5+ is removing Stitches. - Button-styling divergence root cause: the npm-published
v1.1.0tarball (2023-07-21) was built from a working tree with uncommitted modifications tocomponents/Button.tsx. v1.1.2 (PR #158, commit4496362) codifies that tarball form as the committed source of truth — zero consumer-visible behavior change.
🤖 Epic updated with Claude Code
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the canonical token block in the website's app/globals.css, then inspect the existing Stitches components, including components/Button.tsx and components/Accordion.tsx. Choose a single migration batch from the epic before making changes, and verify its components use Tailwind and CVA while preserving existing variant prop names. The overall release is done when Stitches is removed, TypeScript is upgraded, exports and consumer migration guidance are updated, and v2.0.0 is published.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, tailwindcss, typescript
- Domain
- design, frontend, tooling
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100