livepeer / livepeer/design-system

Epic: Stitches → Tailwind v4 + CVA migration to v2.0.0

Open
#156 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
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 @theme token 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' $$PropertyValue declaration-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.tsx to 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 .nvmrc with Node version pin + engines field — #160
  • Upgrade React 17 → 18 peer dep — #161
  • Swap rollup → tsup + remove .npmrc shamefully-hoist + rename tsconfig-rollup.jsontsconfig.build.json — #162
  • Set up Tailwind v4 + CVA alongside existing Stitches (bridge) — #163
  • Remove unused @radix-ui/react-toggle-button@0.0.6 zombie dep blocking np's npm install --engine-strict step — #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' $$PropertyValue symbol 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 @theme block (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; add cn() 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 convert css={{...}} props to className="...". Variant prop names preserved (no primarysecondary rename) — 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 (primarysecondary, neutraloutline, reddestructive) and $primary$foreground token rename — neither serves the website-alignment goal, and both inflate consumer migration cost. Replaced with explicit "copy the website's @theme block" track.

References

  • livepeer/website source of truth: https://github.com/livepeer/website (Next 15 + Tailwind v4 + Favorit Pro). The @theme block in app/globals.css is the canonical brand token set v2.0.0 mirrors.
  • TS 5 blocker: @stitches/react uses $$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 on components/Accordion.tsx during declaration emit. Only path to TS 5+ is removing Stitches.
  • Button-styling divergence root cause: the npm-published v1.1.0 tarball (2023-07-21) was built from a working tree with uncommitted modifications to components/Button.tsx. v1.1.2 (PR #158, commit 4496362) 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.