Skip to content

feat(infra): Storybook 10 + GitHub Integration + Registry Preview Embed #83

@bntvllnt

Description

@bntvllnt

Summary

Set up Storybook 10 as the interactive component playground, deploy to storybook.vllnt.com, integrate with GitHub CI (Chromatic visual testing + PR checks), and embed stories in the registry app as live component previews — replacing the hard-coded ComponentPreview switch.

Motivation

The current component-preview.tsx is a 52KB file with a manual switch statement importing all 93+ components. Every new component requires manual wiring. Visual stories (.visual.tsx) are Playwright CT snapshot tests — non-interactive, no controls, no docs.

Storybook provides: interactive playground with controls, auto-generated docs from TypeScript props, visual regression testing via Chromatic, and iframe embedding — enabling zero-maintenance registry previews.

CURRENT                              TARGET
───────────────────                  ───────────────────────────
Registry App                         Registry App
┌──────────────────┐                 ┌──────────────────────┐
│ ComponentPreview │                 │ ComponentPreview     │
│ ┌──────────────┐ │                 │ ┌─────────────────┐  │
│ │ switch(name) │ │    ────▶       │ │ <iframe src=    │  │
│ │ case "btn":  │ │                 │ │  storybook.     │  │
│ │ case "card": │ │                 │ │  vllnt.com/...  │  │
│ │ case x 93... │ │                 │ │ />              │  │
│ └──────────────┘ │                 │ └─────────────────┘  │
│ 52KB, manual     │                 │ ~2KB, auto-updates   │
└──────────────────┘                 └──────────────────────┘

Phase 1 — Storybook 10 Setup

  • Initialize Storybook 10 in packages/ui/.storybook/
  • Vite builder (aligns with existing Playwright CT Vite setup)
  • Import styles.css + themes/default.css in preview.tsx
  • ThemeProvider decorator for dark/light mode switching
  • Add storybook and build-storybook scripts to packages/ui/package.json
  • Add storybook task to turbo.json
  • Addons:
    • @storybook/addon-a11y — accessibility audit per story
    • @storybook/addon-themes — dark/light toggle in toolbar
    • @storybook/addon-storysource — show story source code
    • @storybook/addon-viewport — responsive viewport testing
    • @storybook/addon-interactions — test interactions in stories
    • @etchteam/storybook-addon-github-link — "View on GitHub" per story (baseURL: https://github.com/vllnt/ui/blob/main/packages/ui/src)

Phase 2 — Stories for All Components

  • File pattern: {name}/{name}.stories.tsx (coexists with existing .visual.tsx Playwright tests)
  • CSF Factories format (Storybook 10 TypeScript-first, less boilerplate)
  • One story per variant/state (mirror .visual.tsx coverage at minimum)
  • Interactive controls (args) for all CVA variants + sizes
  • Compound component stories (Dialog, Select, Dropdown, etc.) show full composition
  • Auto-generated docs from TypeScript props
  • Create pnpm storybook:generate script to scaffold .stories.tsx stubs from component exports
  • Acceptance: every export in src/index.ts has at least one story

Phase 3 — Deploy to storybook.vllnt.com

  • GitHub Actions workflow (.github/workflows/storybook.yml)
  • Use bitovi/github-actions-storybook-to-github-pages action (or Vercel/Cloudflare for subdomain)
  • Deploy to storybook.vllnt.com on push to main
  • CNAME / DNS configuration for subdomain
  • PR builds: build-only for validation (no deploy)
  • Cache: node_modules + .storybook-cache

Phase 4 — Chromatic Visual Testing + PR Checks

  • Add @chromatic-com/storybook addon
  • Add chromaui/action GitHub Action (.github/workflows/chromatic.yml)
  • Snapshot every story in cloud Chrome (free tier: 5k snapshots/month, OSS: 35k/month)
  • PR status checks: UI Tests (visual regression), UI Review (human approval), Publish
  • Every PR gets unique Chromatic URL with visual diff
  • Does NOT replace Playwright CT (keeps local dev snapshots) — adds cloud-based regression
  • Optional: branch protection rule blocking merge until visual changes approved

Phase 5 — Registry Embed (Replace ComponentPreview)

  • Replace 52KB hard-coded component-preview.tsx switch with Storybook iframe embed
  • URL pattern: <iframe src="https://storybook.vllnt.com/iframe.html?id=components-{name}--default&viewMode=story&shortcuts=false&singleStory=true" />
  • Thin ComponentPreview iframe wrapper with:
    • Loading skeleton while iframe loads
    • Height auto-resize (postMessage or ResizeObserver)
    • Dark/light theme sync (globals=theme:dark URL param)
    • Error fallback if Storybook unreachable
    • "Open in Storybook" link button
  • Story ID convention: components-{name}--default (derived from registry slug)
  • Eliminates: massive import tree, manual switch per component, bundle bloat
  • Fallback: keep old ComponentPreview for local dev when Storybook not deployed
  • Add "Interactive Playground" tab alongside static code view on component pages

Phase 6 — Storybook Composition

  • Configure refs in .storybook/main.ts so consumers can compose @vllnt/ui stories into their own Storybook
  • Document: how to reference @vllnt/ui Storybook from external projects

Technical Notes

  • Storybook 10: ESM-only, 29% smaller install, CSF Factories (TypeScript-first), RSC support, Next 16 + Vitest 4 compatible
  • Tailwind setup: Import CSS in .storybook/preview.tsx, Vite builder handles PostCSS automatically
  • Radix primitives: No special config needed — just load CSS variables for theming
  • Embed format: https://storybook.vllnt.com/iframe.html?id={story-id}&viewMode=story&shortcuts=false&singleStory=true
  • Chromatic free tier: 5k snapshots/month (Chrome only), OSS: 35k snapshots/month

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions