Storybook design system documentation: define authority, cover states, and verify changes

Storybook can render, document, test, publish, and share component states. It provides useful evidence of how an implementation behaves, but it does not automatically own the design decisions behind that behavior. Good Storybook design system documentation names the authoritative source for each decision, covers the states and modes the product requires, and records enough evidence to show whether the implementation is current.

Updated July 29, 2026

Start with the authority boundary

Storybook describes itself as a workshop for building components and pages in isolation. Stories preserve states that may be difficult to reach in the full application, and those stories can feed documentation and tests. Both are useful capabilities. The governance problem starts when that convenience becomes an unstated rule that whatever appears in Storybook must be the design system.

A rendered story is evidence produced by component code, a fixture, Storybook configuration, loaded assets, and the current environment. If a button has the wrong focus treatment, editing the story until it looks right may hide the real fault. The semantic token could be wrong. The export could be stale, the component could contain a local override, or the story could apply an artificial background. Correct the layer that owns the decision.

LayerWhat it ownsEvidence to recordCorrection owner
DESIGN.md or approved design sourceUpstream authorityIntent, semantic roles, usage rules, prohibitions, and named exceptionsSource version, relevant rule, and approval stateDesign-system or brand owner
Token or framework exportDelivery artifactTransported values and identifiers for the target stackGenerated version, mapping, diff, and destinationToken or build maintainer
Component codeImplementationReusable structure, supported variants, state behavior, and local constraintsImplementation reference and component testsComponent maintainer
Story fixtureReproduction caseA combination of args, content, context, and environmentStory name, fixture data, globals, and viewportStory or component maintainer
Docs surfaceExplanationHuman-readable claims, examples, guidance, limitations, and linksAutodocs output, MDX content, and last review stateDocumentation owner
Test resultScoped verificationEvidence for the assertion exercised by a checkCheck name, environment, result, and artifactTest or component maintainer
Release observationPublished observationWhat the published product or documentation build exposesBuild identifier, mode, scope, and observed resultRelease owner
Use this map to separate authority from evidence and assign corrections.

A story is not a policy decision

If the upstream source does not define a disabled state, responsive adaptation, validation rule, or accessibility requirement, a polished story does not make that choice authoritative. Mark the requirement unresolved and assign an owner.

Define the component-documentation contract

A component in the Storybook sidebar is still only an inventory entry. The documentation becomes useful when another developer or coding agent can tell what the component is for, which cases it supports, which source governs its appearance, and how its current claims were checked.

Write the contract before expanding the story set. Keep required behavior separate from illustrative examples. A marketing card may need short and long content fixtures, while an internal status badge may have no responsive behavior of its own. Project requirements determine the coverage. A universal checklist would add noise and imply support for states the component cannot reach.

component: ""
purpose: ""
owner: ""
source_authority:
  location: ""
  version_or_date: ""
semantic_roles:
  - role: ""
    source_reference: ""
    implementation_mapping: ""
variants:
  required: []
  unsupported: []
states:
  required: []
  project_defined: []
content_fixtures:
  - name: "typical"
    reason: ""
color_modes: []
responsive_conditions:
  - condition: ""
    expected_result: ""
accessibility_requirements: []
exceptions:
  - decision: ""
    owner: ""
    reason: ""
documentation_surfaces:
  rendered_stories: []
  generated_docs: []
  mdx_guidance: []
  external_sources: []
evidence:
  status: unresolved | observed | tested | accepted
  records: []
unresolved_items: []
last_reviewed: ""
Copyable minimum record for one documented component.

Evidence status matters because the fields do different jobs. An upstream value can be verified while its component mapping remains unresolved. A story may be observed while keyboard behavior remains untested. A visual check can pass even though the documentation still makes an obsolete claim. Don't collapse these into a single complete flag.

  • Unresolved: no authoritative answer or observation has been recorded yet.
  • Observed: a person or tool inspected a named surface under recorded conditions.
  • Tested: a repeatable check exercised a specific assertion and produced a result.
  • Accepted: the authorized reviewer judged the available evidence sufficient for the stated scope.

Put each fact on the right Storybook surface

Storybook offers stories, generated documentation, MDX, testing surfaces, viewports, and sharing workflows. There isn't one best surface. The useful question is which one can carry a particular fact without overstating what that fact proves.

SurfaceUse it forDo not treat it as
Rendered storyRendered storyA reproducible component state with named args, content, context, mode, and viewportProof of every supported state or of production behavior
Generated documentationGenerated documentationComponent metadata and references supported by the implementationA replacement for missing intent, exceptions, or product requirements
MDX explanationMDX explanationPurpose, composition guidance, rationale, limitations, migration notes, and links to authorityProof that the implementation follows the prose
Test evidenceTest evidenceA specific interaction, accessibility, visual, snapshot, or coverage assertionGeneral certification of usability, accessibility, or release readiness
External authoritative sourceExternal authoritative sourceDesign rules, token definitions, product requirements, or policies owned outside StorybookA claim that Storybook automatically remains synchronized with that source
Choose the surface according to the kind of information being documented.

Generated does not mean authoritative

Generated documentation can reduce manual duplication when the implementation contains the relevant metadata. It cannot generate a missing product rule or decide whether a local exception is approved.

Build a story coverage matrix

Start with representative components that expose different failure classes. A button reveals interaction states and focus treatment. An input adds validation and content behavior. Cards expose composition and pressure from long content, while tables add density, overflow, sorting, empty data, and numeric alignment. Choose only components your project actually supports.

For each component, cross the required cases with realistic fixtures. Light and dark modes need separate observations because semantic roles may resolve to different values. Base responsive checks on supported containers or viewports, not an arbitrary collection of device widths. Include expected unchanged behavior in the matrix too, since unrelated movement is often the first sign of an overly broad token or CSS change.

ComponentRequired storiesModes and conditionsEvidence still needed
ButtonButtonDefault, focus, disabled, interaction equivalent, and project-defined destructive caseLight and dark; normal and constrained containerSemantic-role mapping, keyboard observation, and named visual or interaction checks
InputInputEmpty, populated, focus, disabled, and project-defined invalid stateLight and dark; typical and long label or valueLabel and error requirements, focus behavior, and validation observation
CardCardTypical content, long content, optional action, and empty region if supportedLight and dark; standard and narrow containerComposition rule, overflow observation, and unchanged sibling layout
TableTableTypical rows, empty data, dense content, and supported sorting or selection statesLight and dark; wide and constrained containerOverflow behavior, numeric treatment, keyboard checks, and semantic checks
Example coverage matrix. Replace these sample requirements with the supported cases in your product contract.

Don't create a story for every conceivable state. Coverage should trace to a component API, product requirement, design rule, accessibility requirement, supported environment, or observed failure. If none of those supports the case, record it as outside the current contract instead of implying that the component handles it.

Consistency check · No dark-mode parity

The same plan card, built two ways in Ambient Sage.

Drifting system

Pricing

Starter$19/mo

Everything a small team needs to ship a branded UI.

Consistent system

Pricing

Starter$19/mo

Everything a small team needs to ship a branded UI.

What to notice: Mode drift becomes visible when a component uses semantic roles in one mode but retains local values or incomplete mappings in the other.

Inspect a complete upstream token system

The coverage matrix works best when semantic roles and both color modes are explicit before stories are written. You can inspect the free public Ambient Sage kit as an upstream example without assuming any automatic Storybook mapping.

Use Ambient Sage as a bounded intake example

Ambient Sage works here because its public page exposes real upstream artifacts. It documents Plus Jakarta Sans for heading and body roles, JetBrains Mono for technical strings, semantic light and dark roles, DESIGN.md, and exports including DTCG tokens, CSS variables, Tailwind configurations, and a shadcn registry item. Those facts can populate the source side of a documentation record.

Token specimen · real values

Ambient Sage

Live render

Ambient Sage's actual tokens — the same values its exports use.

Color tokensSemantic roles with HEX / HSL / CMYK

Color tokens

Ambient Sage

light · HEX · HSL · CMYK

Core

#F3F4EF

background

H 72 · C0, 0, 2, 4

#1A1C17

foreground

H 84 · C7, 0, 18, 89

#E5E6E0

card

H 70 · C0, 0, 3, 10

#ECEEE8

muted

H 80 · C1, 0, 3, 7

#D8D9D2

border

H 69 · C0, 0, 3, 15

Brand

#FEE951

primary

H 53 · C0, 8, 68, 0

#1A1C17

primary-fg

H 84 · C7, 0, 18, 89

#E5E6E0

secondary

H 70 · C0, 0, 3, 10

#F7E464

accent

H 52 · C0, 8, 60, 3

#FEE951

ring

H 53 · C0, 8, 68, 0

Semantic

#C0392B

destructive

H 6 · C0, 70, 78, 25

#FFFFFF

destructive-fg

H 0 · C0, 0, 0, 0

#2D7238

success

H 130 · C61, 0, 51, 55

#C97D12

warning

H 35 · C0, 38, 91, 21

#545651

muted-fg

H 84 · C2, 0, 6, 66

Charts

#FEE951

chart-1

H 53 · C0, 8, 68, 0

#4A8FD4

chart-2

H 210 · C65, 33, 0, 17

#6BBF8A

chart-3

H 142 · C44, 0, 28, 25

#E07498

chart-4

H 340 · C0, 48, 32, 12

#E8A24B

chart-5

H 33 · C0, 30, 68, 9

Type scaleHeading, body, and mono in the kit's fonts

Typography

Ambient Sage

Scale: compact-product

Density: balanced

Heading · Plus Jakarta Sans · 1.875rem

Sample headline

Subheading · Plus Jakarta Sans · 1.375rem

A warm-sage neutral-surface mobile kit with a single vivid yellow accent, flat tonal cards, and oversized display numerals.

Body · Plus Jakarta Sans · 1rem

Ambient Sage uses a near-white warm-sage canvas (#f3f4ef) with card panels distinguished only by a tonal shift to #e5e6e0, never by shadows or borders. A single vivid yellow (#fee951) is the only saturated color and appears sparingly at component scale as orbs, button fills, and focus rings. Primary data values render as oversized bold hero numerals with a small superscript unit. Typography is a friendly rounded geometric (Plus Jakarta Sans) with no uppercase and no tight tracking, while JetBrains Mono is reserved for hex codes and technical strings. Generous rounding and luminance-only contrast give the whole system a calm, minimal feel.

Mono · JetBrains Mono · 0.8125rem

npx shadcn add ambientsage.json

Aa

Plus Jakarta Sans · Heading

400500600700

Aa

Plus Jakarta Sans · Body

400500600700

ABCDEFGHIJKLM NOPQRSTUVWXYZ

abcdefghijklmnopqrstuvwxyz

0123456789 & @ # % →

Radius & spacingCorner radius, elevation, and spacing steps

Tokens

Ambient Sage primitives

density: balanced

Radius scale

sm · 0.375rem
md · 0.75rem
lg · 1.25rem
xl · 1.75rem

Component radius

button
card
input

Elevation

level 1
level 2
level 3
level 4

Spacing · base 4px

1x
2x
3x
4x
6x
8x
Ambient Sage supplies verified upstream token and typography context. The specimen does not claim that a Storybook project has imported or tested it.

Everything else must remain explicitly unresolved until a real project supplies evidence. Identity Forge does not automatically import a kit into Storybook, create stories, synchronize documentation, define product behavior, or prove visual parity. The intake record below preserves that boundary.

artifact: "Ambient Sage public design kit"
source_status: "verified from frozen public page"
source_authority:
  design_guidance: "published DESIGN.md"
  semantic_tokens: "published light and dark roles"
verified_typography:
  heading: "Plus Jakarta Sans, weights 400 500 600 700"
  body: "Plus Jakarta Sans, weights 400 500 600 700"
  mono: "JetBrains Mono, weights 400 500 700"
available_delivery_formats:
  - "DESIGN.md"
  - "DTCG tokens JSON"
  - "CSS variables"
  - "Tailwind v3 config"
  - "Tailwind v4 theme"
  - "shadcn registry JSON"
storybook_mapping:
  status: "unresolved"
  token_import_path: "unresolved"
  global_mode_control: "unresolved"
  component_role_mapping: "unresolved"
implementation_observations:
  component_behavior: "not observed"
  light_mode_parity: "not observed"
  dark_mode_parity: "not observed"
  responsive_behavior: "not observed"
  accessibility_evidence: "not tested"
acceptance: "blocked until project-specific mapping and evidence exist"
Bounded intake record separating verified upstream facts from unverified Storybook work.

What this example proves

It proves that the named public upstream artifacts and roles are available. It does not prove that a component consumes them, that a story covers the correct states, or that a rendered result meets project requirements.

Verify one controlled design-system change

A static review can confirm that documentation looks plausible. A controlled change checks whether the documented chain actually propagates. Choose one bounded semantic-role change in a development or review context where the change is authorized. The goal is to observe named consumers and detect unrelated movement, not to restyle the whole library.

Suppose the approved upstream source changes the value assigned to a focus-ring role. Before applying it, list the components and stories expected to consume that role. Name the surfaces that should remain unchanged too, such as card backgrounds, destructive text, and chart series. Now the change is a falsifiable check.

  1. 1

    Freeze the source decision

    Record the authoritative artifact, version, semantic role, old value, approved new value, owner, and reason. If the change is only hypothetical, stop before editing and use the record as a planning exercise.

  2. 2

    Name expected consumers

    List the components, stories, modes, and states expected to change. Include at least one representative focus state in light and dark mode when both modes are supported.

  3. 3

    Name expected unchanged surfaces

    List nearby roles and components that must not move. This catches broad selectors, alias mistakes, and local overrides that a target-only review misses.

  4. 4

    Update the delivery artifact

    Record the generated output or mapping change. A changed source with an unchanged export is a stale-delivery failure, not a Storybook documentation problem.

  5. 5

    Observe stories and collect tests

    Inspect the named stories under recorded modes, states, viewports, and fixtures. Attach each test result to the assertion it supports. Keep missing checks marked unresolved.

  6. 6

    Assign a disposition

    Accept only when expected consumers changed, expected unchanged surfaces held, documentation claims remain accurate, and no blocking evidence gap remains. Use revise for bounded defects and block when authority or required evidence is missing.

change_id: "focus-ring-role-example"
change_status: "planned, not executed"
authoritative_source:
  artifact: ""
  version: ""
  owner: ""
semantic_role: "focus ring"
approved_change:
  from: ""
  to: ""
expected_consumers:
  - component: "Button"
    stories: ["Focus"]
    modes: ["light", "dark"]
expected_unchanged:
  - "Card background"
  - "Destructive text"
  - "Chart series"
delivery_evidence:
  generated_output: "unresolved"
  mapping_diff: "unresolved"
story_observations:
  light: "unresolved"
  dark: "unresolved"
test_evidence: []
local_overrides: []
exceptions: []
unresolved_items:
  - "Project mapping not supplied"
  - "No implementation was executed in the frozen evidence"
disposition: "block"
disposition_reason: "Required project evidence is absent"
Controlled-change record. The example stays blocked because no Storybook implementation or test was observed.

Keep expected and observed results separate

Write expected consumers before applying the change. Record the observations afterward in separate fields. If expectations are edited to match the result, the check can no longer reveal missing propagation or unrelated drift.

Diagnose drift in ownership order

When a story differs from the intended system, start at the highest authoritative layer and move toward the rendered surface. This keeps you from fixing a symptom in a fixture while every real consumer remains wrong.

  1. Upstream source: Is the intended semantic role or rule explicit, current, approved, and owned?
  2. Export mapping: Did the correct source version produce the artifact used by the project, with the expected identifier and mode values?
  3. Component implementation: Does the component consume the mapped semantic role, or does a local value, selector, or variant override it?
  4. Story fixture: Does the story reproduce a supported state with realistic args, content, context, globals, and viewport?
  5. Documentation claim: Does generated documentation or MDX describe the current component API, limitations, exceptions, and authority accurately?
  6. Test environment: Does the check load the same tokens, fonts, decorators, mode settings, and component version as the documented story?
  7. Release observation: Does the published Storybook or product build contain the reviewed artifacts, and does it show the accepted result?

Stop at the first layer that fails and route the correction there. Source ambiguity needs an authorized design decision. A stale export needs regeneration or mapping work. A component override needs an implementation fix, while a misleading fixture needs story maintenance. If a released build contains old artifacts, it needs release correction. The visual symptom may be identical, but the responsible owner isn't.

Set accept, revise, and block criteria

Documentation is current only within a declared scope. A button contract can be accepted while a table remains unresolved. State the component versions, modes, viewports, fixtures, environments, and evidence included in the decision so readers don't mistake partial coverage for a library-wide guarantee.

DispositionUse whenRequired follow-up
AcceptAcceptAuthority is named, required stories exist, expected observations hold, evidence supports the stated claims, and unresolved items are non-blocking within scopeRecord reviewer, date, versions, scope, and retained limitations
ReviseReviseThe authority is clear and defects are bounded, such as a stale fixture, missing supported state, inaccurate MDX claim, or local overrideAssign each defect to its owning layer and repeat affected checks
BlockBlockAuthority is unclear, a required state or mode is absent, expected consumers fail to update, unrelated surfaces drift, or evidence is too weak for the claimResolve the missing decision or evidence before presenting the documentation as current
Use a bounded disposition instead of a vague documentation complete label.

This workflow does not replace Storybook's official installation, framework, API, addon, migration, or configuration references. Nor does it prove accessibility conformance or release readiness. It provides a narrower record those references do not: which decisions Storybook is showing, which states are covered, who owns exceptions, and what evidence supports a current claim.

Questions about Storybook design system documentation

Should Storybook be the source of truth for a design system?

Storybook can be the primary place where people observe and explore implemented components, but authority should be assigned decision by decision. Design intent may live in DESIGN.md or another approved source, token values in a governed token system, behavior in component code and product requirements, and evidence in stories and tests.

How many stories should each component have?

Use enough stories to cover the component's supported variants, reachable project-defined states, realistic content, required modes, and responsive conditions. Don't create stories for hypothetical cases with no support in the component API, requirements, design rules, accessibility requirements, or observed failures.

Are Autodocs and MDX interchangeable?

No. Generated documentation works well for information derived from the implementation. MDX is better suited to purpose, composition guidance, rationale, limitations, exceptions, and links to external authority. Neither proves that the rendered implementation follows every documented claim.

Does a visual test prove the design system is implemented correctly?

It supports the specific visual assertion and environment covered by that test. By itself, it does not prove correct product behavior, accessibility conformance, semantic token ownership, every mode, or production parity.

Can Identity Forge import a design kit into Storybook automatically?

The frozen product evidence establishes no such automatic Storybook integration. Identity Forge can supply DESIGN.md, semantic light and dark tokens, typography and spacing guidance, and developer exports. The consuming project must map those artifacts to its components, stories, documentation, and tests.

When should Storybook documentation be blocked?

Block the handoff when required authority is unclear, a supported state or mode lacks coverage, expected consumers do not reflect an approved change, unrelated surfaces drift, documentation contradicts the implementation, or the evidence cannot support the claim that the documentation is current.

Start with one representative component. Write its contract and capture its required stories in light and dark mode. Then plan or run one authorized semantic-role change against named consumers and unchanged surfaces. Record the result as accept, revise, or block before treating that part of Storybook as current.

Sources