Skip to content

Storybook

Storybook is the interactive workshop for the React components in this library. Every component is rendered in isolation with live controls for its props, an auto-generated API table, and an accessibility audit.

  1. Install dependencies, if you have not already:

    Terminal window
    npm install
  2. Start the Storybook dev server:

    Terminal window
    npm run storybook
  3. Open http://localhost:6006.

To produce a static build — for deploying the component documentation, or for a CI artifact:

Terminal window
npm run build-storybook

The output lands in storybook-static/, which is gitignored.

Pick a component in the sidebar and you land on its Docs page, which assembles:

  • The component description, taken from the JSDoc on the story file.
  • An API table generated from the exported Props type, including each prop’s JSDoc comment, its accepted values, and its default.
  • Every story, each with its own description.

Switch to the Canvas tab for a single story and you get:

  • Controls — change any prop live and watch the component re-render.
  • Accessibility — an axe audit of the rendered output.
  • Show code — the exact JSX for the current prop combination.

Storybook renders src/components/react/ only.

astro-breadcrumb is also excluded. The @fpkit/react Breadcrumb it wraps builds its trail from window.location.pathname and uses the routes prop only as a segment-to-label lookup, so inside Storybook’s iframe it would always show Storybook’s own path rather than a realistic trail.

Colocate the story next to its component as Thing.stories.tsx:

src/components/react/Thing.stories.tsx
import type { Meta, StoryObj } from '@storybook/react-vite'
import Thing from '#components/react/Thing'
/** This JSDoc becomes the component's description on the Docs page. */
const meta = {
title: 'React/Thing',
component: Thing,
argTypes: {
variant: {
control: 'inline-radio',
options: ['primary', 'secondary'],
description: 'Visual style of the component.',
},
},
args: { variant: 'primary' },
} satisfies Meta<typeof Thing>
export default meta
type Story = StoryObj<typeof meta>
/** This JSDoc becomes the story's description. */
export const Primary: Story = {}
export const Secondary: Story = {
args: { variant: 'secondary' },
}

Follow these conventions so stories stay consistent with the rest of the codebase:

  • Import through the mandatory # alias, never a relative path.
  • Type meta with satisfies Meta<typeof Thing> and stories with StoryObj<typeof meta>, so args are checked against the real props.
  • Title stories React/<ComponentName> to keep the sidebar grouped.
  • Treat the JSDoc as the documentation — autodocs renders it verbatim.

Stories load the same stylesheets as src/layouts/Base.astro, so what you see matches the real site:

  1. @fpkit/acss/styles
  2. src/styles/index.scss

The SCSS entry point is imported directly, so editing any partial under src/styles/ hot-reloads the canvas — no separate npm run sass needed.

The Accessibility panel runs axe on every story. This project targets WCAG 2.1 Level AA, so treat reported violations as defects in the component rather than in the story. Violations are surfaced but do not fail a story.

Configuration lives in .storybook/:

Story discovery, addons, the @storybook/react-vite framework, and react-docgen-typescript for prop tables.

The MDX glob is scoped to src/stories/ deliberately — a broad src/**/*.mdx also matches the Starlight content collection you are reading right now, and Storybook refuses to index it.

For the full technical reference, including troubleshooting, see project-docs/04-integrations/storybook.md.