docs: MVP-7 Badge pilot — full JSDoc contract + first composed README.mdx#6212
docs: MVP-7 Badge pilot — full JSDoc contract + first composed README.mdx#6212caseyisonit wants to merge 5 commits into
Conversation
End-to-end pilot of the new per-entity authoring shape on `<swc-badge>`.
Four parts, one PR:
1. Class JSDoc on `Badge.ts` — extended to the full contract:
- existing `@status preview` / `@since 0.0.1` preserved
- new `@summary` (one-line subtitle, consumed by the new `<Subtitle />`
block from MVP-5)
- new taxonomy: `@genre component`, `@category status-display`
- new `@related status-light,tag` (sibling cross-links)
- new `@RSPparity partial` (parity status against React Spectrum 2)
- new `@a11yPattern non-interactive-color-status` (accurate to the
component — badge is non-interactive, conveys state via color + text)
- 14 `@cssproperty` entries covering every public `--swc-badge-*`
custom property surfaced by `badge.css`
- existing `@example` blocks preserved (code-only, per the new
stories-have-no-prose contract); fixed an invalid `fixed="fill"` value
in the second example to `fixed="block-start"` (`fill` is not in
`FIXED_VALUES`)
`@slot` declarations stay on `Badge.base.ts` where they already live;
CEM carries them through via `inheritedFrom`. No `@fires` (Badge
dispatches no events) and no `@csspart` (no shadow parts exposed) —
documenting what exists, not inventing surface.
2. New `2nd-gen/packages/swc/components/badge/README.mdx` — the first
composed-template entity README. Becomes Badge's docs page (Storybook's
`docs.defaultName` is `'README'`). Sections, in order:
- `<Title />` / `<StatusBadge />` / `<Subtitle />` (subtitle reads
`@summary` from CEM)
- `<Description />` (class-level prose)
- `<GettingStarted tags={['migrated']} />` (install + import)
- **API** — `<Primary />`, `<ApiTable />`, `<EventsTable />` (renders
nothing for badge), `<CssPartsTable />` (also empty), `<CssPropsTable />`
- **Usage** — three executable examples (`Sizes`, `SemanticVariants`,
`Outline`) embedded via `<EmbedStory of={Stories.X} />`, each preceded
by a keyword-first `###` heading and ≤3 sentences of per-example prose
- **Accessibility** — narrative + cross-link to consumer migration guide
- **Migration** — pointer to existing `consumer-migration-guide.mdx`
- `<RelatedEntities />` (reads `@related` from CEM)
3. `badge.stories.ts` — JSDoc prose stripped from every story export.
Stories now describe **executable configurations only**; concept prose
(anatomy, variant guidance, accessibility narrative) lives in the
README or class JSDoc, not duplicated in story files. The component-
level `parameters.docs.subtitle` was already absent — no change there.
4. `eslint.config.js` — extends the `jsdoc/check-tag-names` allowlist with
the six new tags introduced by MVP-5's `swcJsdocTagsPlugin` (`@summary`,
`@genre`, `@category`, `@related`, `@RSPparity`, `@a11yPattern`).
Without this, the lint hook rejects the new Badge JSDoc. The
enforcement-side counterpart to the parser changes that landed in
MVP-5.
Smoke-tested:
- `yarn analyze` — CEM emits all new fields on Badge: `summary`, `genre`,
`category`, `related`, `RSPparity`, `a11yPattern`, plus
`cssProperties[]` with all 14 `--swc-badge-*` props (each with its
description). Existing `status`/`since`/`slots`/`tagName` preserved.
- `npx tsc --noEmit` — no new type errors (only the pre-existing
unrelated `@vitest/browser` typings issue).
- `yarn generate:contributor-docs` — docs pipeline healthy.
Stacks on `caseyisonit/docs-mvp-5-cem-extension`. After merge, badge
serves as the canonical example other entities clone in Phase 2.
|
The leading copyright comment used backslash-escaped asterisks
inside a JSX expression (`{/\*...\*/}`), which acorn cannot parse
as valid JavaScript. Replace with a standard JSX comment
(`{/* ... */}`) so the file indexes correctly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous fix that converted the JSX-comment copyright header to
plain `{/* */}` syntax was reverted by prettier in the lint-staged
pre-commit hook — prettier's markdown plugin escapes the `*` chars
back to `\*`, which makes acorn unable to parse the JSX expression.
Other handwritten MDX in this repo (DocumentTemplate.mdx, the four
learn-about-swc/*.mdx pages) carry no copyright header at all; the
LICENSE file at the repo root covers them. Match that convention so
prettier has nothing to mangle.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
With the new README.mdx defining the canonical docs page for
'Components/Badge' via <Meta of={Stories} />, the Playground
story can no longer also opt into autodocs at the same kind ID
— Storybook 10 errors with 'created a component docs page ...
but also tagged the CSF file with autodocs'.
The Playground keeps its 'dev' tag so it stays visible in the
local sidebar; production builds drop it as before.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
📚 Branch Preview Links🔍 First Generation Visual Regression Test ResultsWhen a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:
Deployed to Azure Blob Storage: If the changes are expected, update the |
Description
End-to-end pilot of the new per-entity authoring shape on
<swc-badge>. Badge is small, already migrated, and already referenced in.ai/rules/stories-documentation.mdas the exemplar — exactly the right component to prove out the new contract before Phase 2 rolls it across all migrated entities.Four parts, one PR:
1. Class JSDoc on
Badge.ts— full contract@status preview/@since 0.0.1preserved@summary(one-line subtitle, consumed by the new<Subtitle />block from MVP-5)@genre component,@category status-display@related status-light,tag(sibling cross-links)@RSPparity partial(parity status against React Spectrum 2)@a11yPattern non-interactive-color-status— accurate to the component (Badge is non-interactive, conveys state via color + text). Diverged from the plan's suggestedaria-describedby-ownerbecause Badge is referenced by ARIA describedby, not the owner of one@csspropertyentries covering every public--swc-badge-*custom property surfaced bybadge.css(each with a description)@exampleblocks preserved (code-only, per the new stories-have-no-prose contract); fixed an invalidfixed=\"fill\"value in the second example tofixed=\"block-start\"(fillis not inFIXED_VALUES)@slotdeclarations stay onBadge.base.tswhere they already live; CEM carries them through viainheritedFrom. No@fires(Badge dispatches no events) and no@csspart(no shadow parts exposed) — documenting what exists, not inventing surface.2. New
2nd-gen/packages/swc/components/badge/README.mdxThe first composed-template entity README. Becomes Badge's docs page (Storybook's
docs.defaultNameis'README'). Sections, in order:<Title />/<StatusBadge />/<Subtitle />(subtitle reads@summaryfrom CEM)<Description />(class-level prose)<GettingStarted tags={['migrated']} />(install + import)<Primary />,<ApiTable />,<EventsTable />(renders nothing for Badge),<CssPartsTable />(also empty),<CssPropsTable />Sizes,SemanticVariants,Outline) embedded via<EmbedStory of={Stories.X} />, each preceded by a keyword-first###heading and ≤3 sentences of per-example proseconsumer-migration-guide.mdx<RelatedEntities />(reads@relatedfrom CEM)3.
badge.stories.ts— prose strippedJSDoc prose removed from every story export. Stories now describe executable configurations only; concept prose (anatomy, variant guidance, accessibility narrative) lives in the README or class JSDoc, not duplicated in story files. The component-level
parameters.docs.subtitlewas already absent — no change there.4.
eslint.config.js— JSDoc tag allowlist updateExtends
jsdoc/check-tag-names.definedTagswith the six new tags introduced by MVP-5'sswcJsdocTagsPlugin(@summary,@genre,@category,@related,@RSPparity,@a11yPattern). Without this, the lint-staged hook rejects the new Badge JSDoc. The enforcement-side counterpart to MVP-5's parser changes.Motivation and context
Per the docs-overhaul v2 plan, every entity (component, controller, pattern, token family) eventually adopts the same three-file shape: class JSDoc +
README.mdx+ optional executable-only stories. MVP-5 built the parser and block library; this PR exercises both end-to-end on Badge.Without a real pilot, the CEM extension and block library are theoretical. After this lands, Badge is the canonical example other entities clone during Phase 2's per-entity rollout.
Related issue(s)
Stacks on #6211 (MVP-5 CEM extension). Unblocks Phase 2's per-entity rollout.
Author's checklist
Manual review test cases
Badge docs page renders the new README.
2nd-gen/packages/swc, runyarn analyze && yarn storybook@summary), description prose, install snippet, API section with property/attribute table + CSS custom properties table (no events table, no CSS parts table — Badge has none), Usage section with three embedded canvases (Sizes, SemanticVariants, Outline), Accessibility section, Migration pointer, Related entities list.CSS custom property descriptions surface.
--swc-badge-*props appear, each with its description from the JSDocStorybook subtitle now reads from CEM.
@summary)<swc-status-light>)<Subtitle />block from MVP-5 falls back when@summaryis absent)Stories sidebar still works.
Lint and analyze pass cleanly.
yarn lint:eslint -- --no-error-on-unmatched-pattern 2nd-gen/packages/swc/components/badge2nd-gen/packages/swc, runyarn analyzeDevice review
Accessibility testing checklist
Required: Complete each applicable item and document your testing steps.
Keyboard (required — document steps below)
Badge is a non-interactive, non-focusable element. The new README adds no new interactive surface — all blocks render static HTML (tables, headings, links, embedded canvas iframes). Confirm no regressions in surrounding examples.
Screen reader (required — document steps below)
Tables, headings, and links use semantic HTML; no custom ARIA on the README itself. The Badge component's a11y model (already documented in the existing consumer migration guide and now in the README accessibility section) is unchanged.
<swc-badge variant=\"positive\">Approved</swc-badge>— VoiceOver announces "Approved" as static text (no role, not focusable), confirming the non-interactive a11y contract