Skip to content

Storybook UI Testing Plan

Reference: How to automate UI tests with GitHub Actions

Hosting Strategy — Single SWA, /storybook/ subdirectory

The Storybook static output is co-hosted with MkDocs on the existing Azure Static Web App.

How it works:

  • MkDocs builds to site/ — already the SWA app_location
  • Storybook builds to storybook-static/ (via build-storybook -o storybook-static)
  • CI copies storybook-static/site/storybook/ before the SWA deploy step
  • SWA serves the entire site/ tree; /storybook/ is just a subdirectory — no extra infra needed

SWA config changes required (docs/staticwebapp.config.json):

  • The current navigationFallback rewrites all unmatched paths to /index.html (MkDocs root). Storybook's own index.html must be excluded from this fallback, otherwise deep-linking inside Storybook breaks.
  • Add /storybook/* to the navigationFallback.exclude list.
  • Auth (/* → authenticated) already covers /storybook/* — no extra route rules needed.

Result: Storybook reachable at https://docs.sven-relijveld.com/storybook/ (same auth, same SWA, zero extra cost).

Reference: Azure SWA officially recommends separate instances per app, but the subdirectory + copy approach is a well-established pattern for related static assets (docs + design system) served under the same auth boundary. See: https://learn.microsoft.com/en-us/answers/questions/2260777/is-it-possible-to-host-multiple-static-app-in-sing


Phase 1 — Foundation ✅ DONE (PR #390, 2026-05-06)

  • Storybook 10 + @storybook/react-vite, Tailwind v4, ThemeProvider wrapper
  • 8 shadcn/ui primitive stories: Button, Card, Badge, Input, Dialog, Tabs, Avatar, Alert
  • 6 portfolio section stories: Navigation, HeroSection, Footer, ProjectsSection, ExperienceSection, SkillsSection
  • Vitest browser integration (@vitest/browser + Playwright), 45 interaction tests passing
  • Scripts: storybook (dev), storybook:build (static output)
  • docs/staticwebapp.config.json: /storybook/* excluded from nav fallback

Phase 2 — CI + Hosting ✅ DONE (PR #390, 2026-05-06)

  • Chromatic job in test.yml, wired into gate required check
  • deploy-docs.yml: builds Storybook, copies storybook-static/site/storybook/ before SWA deploy
  • Storybook served at https://docs.sven-relijveld.com/storybook/

Phase 2.5 — Custom Theming ✅ DONE (2026-05-07, current branch)

  • tokens.ts — design tokens extracted from index.css (colors, typography, radius)
  • lightTheme.ts / darkTheme.ts — Storybook UI chrome themed to match sven-relijveld.com
  • manager.ts — applies theme on load based on prefers-color-scheme
  • OneDNA logo: pink logo for light chrome, white logo for dark chrome
  • Canvas toolbar toggle (sun/moon) controls component rendering theme independently

Phase 3 — Missing Component Stories ✅ DONE

3a — Portfolio Sections ✅

Component Status
about-section.tsx ✅ Default + DarkMode
contact-section.tsx ✅ Default + DarkMode + FilledForm .play()
awards-section.tsx ✅ Default + DarkMode
certifications-section.tsx ✅ Done
how-its-made-section.tsx ✅ Default + DarkMode

3b — Dialog / Modal Components ✅

Component Status
cv-download-dialog.tsx ✅ DownloadOnly + WithGeneration + DialogOpen .play() feature-flag variants
admin-modal.tsx ✅ Closed + Open + OpenAdminPortalButton .play()

3c — shadcn/ui Primitives (documentation value)

Worth adding for design-system docs — these are interactive and have meaningful variants:

Component Priority
accordion.tsx MEDIUM
select.tsx MEDIUM
dropdown-menu.tsx MEDIUM
sheet.tsx MEDIUM
table.tsx MEDIUM
checkbox.tsx LOW
switch.tsx LOW
radio-group.tsx LOW
textarea.tsx LOW

Not worth adding: separator, skeleton, label, aspect-ratio, collapsible, resizable, scroll-area, toaster, toggle, toggle-group, menubar, context-menu, hover-card, input-otp, breadcrumb, command, navigation-menu, popover, progress, slider, pagination

3d — Not worth adding (pages + pure wrappers)

  • Pages (home.tsx, about.tsx, projects.tsx, etc.) — better covered by E2E
  • theme-provider.tsx — context only, no UI
  • mode-toggle.tsx — thin wrapper around theme context

Deferred / Out of Scope

  • Separate SWA instance — not needed; subdirectory approach covers the use case at zero extra cost