Skip to content

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

@rickstaa

Description

@rickstaa

Goal

Modernize @livepeer/design-system by migrating from Stitches (deprecated/unmaintained) to Tailwind CSS v4 + CVA, landing as v2.0.0 aligned with the new Livepeer website styling.

Why

  • Stitches is unmaintained — no active development, growing security debt
  • Outdated stack — Node 16, TypeScript 4.7, React 17 peer dep, rollup v2
  • Alignment — v2.0.0 should match the new Livepeer website's visual design language
  • 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 Align Button to the published 1.1.0 tarball behavior (restores subdued primary / neutral / color-loop + missing transparentWhite / transparentBlack variants; base styles and sizes match the tarball) No (behavior patch; matches what Explorer already runs)
v1.2.0 Infrastructure modernized (pnpm, tsup, React 18 peer dep, .nvmrc), Tailwind infra in place. TS stays at 4.7 — TS 5+ is blocked by Stitches' $$PropertyValue declaration emit incompatibility (TS4118). No (minor, additive)
v2.0.0 Stitches fully removed, all components on Tailwind + CVA, TypeScript 5.9+, new website styling Yes (major)

Infrastructure phase (pre-Tailwind) → v1.2.0

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.

Component migration phase (Stitches → CVA) → v2.0.0

Component batches migrated to Tailwind + CVA with shadcn-aligned variant vocabulary (default / outline / secondary / ghost / destructive). Each batch is a standalone PR.

  • Button + variant audit (align to shadcn conventions)
  • Form primitives (Input, Textarea, Label, Checkbox, Radio, Switch, Select, Slider)
  • Overlay components (Dialog, AlertDialog, Popover, Tooltip, HoverCard, DropdownMenu, ContextMenu)
  • Layout components (Box, Flex, Grid, Container, Section, Separator)
  • Data display (Avatar, Badge, Card, Table, Progress, AspectRatio)
  • Navigation (Tabs, Accordion, ScrollArea, Menu)
  • Typography (Heading, Text, Code, Link, Blockquote)
  • 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)
  • Align visual design with new Livepeer website styling
  • Update public API exports (drop styled, css, getCssText, globalCss, keyframes, config; add cn(), theme tokens, CVA recipes)
  • Rename shadcn-incompatible tokens introduced in ui: add two more color options #136$primary token (currently black/white high-contrast) → $foreground; brand green scale stays as $primary*. Matches shadcn convention where primary = brand color.
  • Align Button variants to shadcn vocabulary (default / outline / secondary / ghost / destructive):
    • primarysecondary (the subdued tonal form restored in v1.1.2 — maps to shadcn secondary)
    • neutraloutline
    • Introduce default as the new saturated CTA variant (shadcn convention)
    • red color-loop variant → destructive
    • Drop remaining color-loop variants (green, blue, etc.) — replace with color prop, className override, or per-consumer composition per shadcn convention
  • Migration guide for consumers (include token rename + variant rename)
  • 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 — Explorer just bumps the version and picks up the same visual behavior it already runs today.
  • v1.2.0 — additive infra modernization (pnpm, tsup, React 18 peer dep, Tailwind bridge). Consumers can upgrade safely. TS stays at 4.7.
  • v2.0.0 — breaking: Stitches removed, TS 5.9+, consumer apps need explicit migration PRs to adopt new API, variant names (primarysecondary, neutraloutline, reddestructive), and token renames.

References

  • Migration decision date: 2026-04-04
  • 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 the same TS4118 error on components/Accordion.tsx during rollup-plugin-typescript2 declaration emit. The only path to TS 5+ is removing Stitches from the codebase.
  • 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 fix(Button): restore uncommitted v1.1.0 tarball state as source of truth #158, commit 4496362) codifies that tarball form as the committed source of truth — zero consumer-visible behavior change.
  • shadcn/ui button variant conventions: https://ui.shadcn.com/docs/components/button

🤖 Epic created with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions