Skip to content

docs(swc): convert 2nd-gen component story JSDoc to per-component MDX - #6349

Merged
caseyisonit merged 18 commits into
mainfrom
caseyisonit/docs-to-mdx
Jun 1, 2026
Merged

docs(swc): convert 2nd-gen component story JSDoc to per-component MDX#6349
caseyisonit merged 18 commits into
mainfrom
caseyisonit/docs-to-mdx

Conversation

@caseyisonit

Copy link
Copy Markdown
Contributor

Description

Move long-form documentation that previously lived as JSDoc comments above story exports in .stories.ts files into per-component MDX files at the component root. Each MDX file uses Storybook doc blocks (<Meta of={...} />, <Canvas of={Story} />) to render stories explicitly, and becomes the authoritative Docs page for that component, replacing the template-driven page generated by DocumentTemplate.mdx on a per-component basis.

Scope (this PR): 9 components + 2 internal stories + shared infrastructure.

  • Components: badge, avatar, color-loupe, divider, progress-circle, status-light, typography, illustrated-message, button, tabs
  • Internal components: asset (.internal.mdx), icon (.internal.mdx)
  • Shared blocks: DocsHeader and DocsFooter (in 2nd-gen/packages/swc/.storybook/blocks/) own all the standard chrome at the top and bottom of every docs page, so the template-driven page and per-component MDX share the exact same surface with no duplicate boilerplate.
  • Template rewrite: DocumentTemplate.mdx now composes itself from the new blocks; components without a per-component MDX continue to render through it unchanged.
  • Sidebar refresh: Auto-generated preview.ts registrations for several new migration-analysis contributor docs (action-button, button-group, close-button, grid, infield-button, link, popover, changelog strategy) — picked up from update-nav.js.

Patterns and controllers are deferred to a follow-up PR (saved on caseyisonit/docs-mdx-patterns). This PR is scoped to components only.

Motivation and context

Story-level JSDoc was the only mechanism for long-form prose attached to each story, which forced documentation-only stories (tags: ['description-only']) and section-order parameters to influence rendering order. Moving to MDX:

  • Eliminates the description-only anti-pattern: prose-only sections live in MDX without needing a fake story to hang JSDoc on.
  • Removes section-order workarounds: ordering is explicit in MDX.
  • Enables a single, hand-authored source of truth per component, with explicit <Canvas of={Story} /> references that survive lint and refactors.
  • Sets up patterns and controllers to use the same DocsHeader / DocsFooter shell (out of scope for this PR but enabled by it).

The new MDX structure mirrors the section order of DocumentTemplate.mdx so local builds match production rendering: Anatomy → Upcoming features → Usage → Options → States → Behaviors → Accessibility → API → Feedback.

Related issue(s)

  • Tracked internally; no external ticket.

Screenshots (if appropriate)

Visual parity verified by spot-checking badge, status-light, and tabs Docs pages against the template-driven rendering.

Author's checklist

  • I have read the CONTRIBUTING and PULL_REQUESTS documents.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices
  • I have added automated tests to cover my changes.
  • I have included a well-written changeset if my change needs to be published.
  • I have included updated documentation if my change required it.

Reviewer's checklist

  • Includes a Github Issue with appropriate flag or Jira ticket number without a link
  • Includes thoughtfully written changeset if changes suggested include patch, minor, or major features
  • Automated tests cover all use cases and follow best practices for writing
  • Validated on all supported browsers
  • All VRTs are approved before the author can update Golden Hash

Manual review test cases

  • Per-component Docs pages render via MDX

    1. Run yarn storybook in 2nd-gen/packages/swc/
    2. Open each of: /docs/components-badge--docs, components-avatar--docs, components-color-loupe--docs, components-divider--docs, components-progress-circle--docs, components-status-light--docs, components-typography--docs, components-illustrated-message--docs, components-button--docs, components-tabs--docs
    3. Expect: each page renders header (title, status badge, subtitle, description, overview, getting started), all section headings in canonical order (Anatomy, Upcoming features where applicable, Options, States, Behaviors, Accessibility), API table, controls, and feedback link.
  • Unconverted components still render through DocumentTemplate

    1. Open /docs/components-accordion--docs (no MDX file exists)
    2. Expect: page still renders end-to-end via the rewritten DocumentTemplate.mdx, indistinguishable from the previous template output.
  • Internal Docs pages render

    1. In dev mode, open /docs/components-asset--docs and /docs/components-icon--docs
    2. Expect: each renders from its .internal.mdx. Confirm they are excluded from production builds (rerun with NODE_ENV=production).
  • Story title and section order match production

    1. Compare badge, status-light, and tabs Docs pages against the production deploy.
    2. Expect: per-story ### Title headings (Title Case for PascalCase exports without storyName, exact string for those with storyName) appear in the same order and with the same casing as production.

Device review

  • Did it pass in Desktop?
  • Did it pass in (emulated) Mobile?
  • Did it pass in (emulated) iPad?

Accessibility testing checklist

Required: Complete each applicable item and document your testing steps.

  • Keyboard (required — document steps below)

    1. From the Docs page of any converted component (e.g. /docs/components-button--docs), press Tab through the page.
    2. Expect: focus order moves through the in-page anchor links (Anatomy, Options, States, Behaviors, Accessibility, API, Feedback), then into each rendered Canvas (where interactive components like buttons are focusable), then to the "Open an issue" feedback link.
    3. Confirm focus is visible at every stop and no focus traps exist inside <Canvas> regions.
  • Screen reader (required — document steps below)

    1. With VoiceOver (macOS) or NVDA (Windows), navigate the Docs page by heading.
    2. Expect: heading levels read in order — h1 (component title), h2 (section: Anatomy / Options / etc.), h3 (per-story title where hideTitle=false), h4/h5 (subsections within JSDoc-derived prose).
    3. Confirm each rendered story Canvas exposes its component(s) with role, name, and state as defined in the component's accessibility behavior. No new announcements are introduced by the MDX wrapper itself.

caseyisonit and others added 13 commits May 28, 2026 12:26
Introduce two genre-aware Storybook doc blocks that own the standard top
and bottom of every per-unit docs page. Components, patterns, and
controllers compose a page as:

  <Meta of={Stories} />
  <DocsHeader />
  ...prose + Canvas references...
  <DocsFooter />

DocsHeader renders Title, StatusBadge, Subtitle, Description, the overview
story, and getting-started instructions. DocsFooter renders the API
section (skipping ApiTable for tag='controller'), Primary, Controls,
optional custom API stories, and the feedback link.

Rewrite DocumentTemplate.mdx in terms of the new blocks so the
template-driven docs page and the forthcoming per-unit MDX pages share
the exact same chrome with no duplicate boilerplate to drift.

Also adds research.md documenting the broader conversion plan.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
….mdx

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Auto-generated by update-nav.js for newly added migration analysis docs
(action-button, button-group, close-button, grid, infield-button, link
migration plan, popover migration plan, changelog strategy guide).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented May 28, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3ac83db

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@caseyisonit caseyisonit May 28, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the DocsHeader blocks will be refined in a future PR but this reflects the current patterns that are consistent across all docs so far. Heavily based on DocumentTemplate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto generated from merges to main that werent picked up before

Comment on lines +116 to +133
## Behaviors

### Text Wrapping

When a badge's label is too long for the available horizontal space, it wraps to form multiple lines.
Text wrapping can be controlled by applying a `max-inline-size` constraint to the badge.

This ensures badges remain readable even with longer status messages or category names.

<Canvas of={BadgeStories.TextWrapping} />

### Inline

Badges flow naturally within prose text to annotate inline content such as headings, labels, list items, or table cells.

Because `<swc-badge>` renders as `inline-flex`, it participates in the normal text flow without any extra wrapper styling required. Use small (`s`) badges in most inline contexts to avoid disrupting line height.

<Canvas of={BadgeStories.Inline} />

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will notice the order some sections (behaviors) varies from production, this is because its honoring the authoring order whereas production was following alpha order when rendering because we didnt use the section-order parameter. this is an acceptable difference as long as the content for each story is still accurate.

@caseyisonit
caseyisonit marked this pull request as ready for review May 28, 2026 19:00
@caseyisonit
caseyisonit requested a review from a team as a code owner May 28, 2026 19:00
@caseyisonit caseyisonit added Component:Documentation Issues or PRs involving changes to docs or docs website. Component prefix is for Jira integration. Status:Ready for review PR ready for review or re-review. gen2 These issues or PRs map to our 2nd generation work to modernizing infrastructure. labels May 28, 2026
@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

📚 Branch Preview Links

🔍 First Generation Visual Regression Test Results

When 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: pr-6349

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.

@rise-erpelding rise-erpelding left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall! I think the only real blocker would be removing the research.md doc unless there's a reason we want it!

*
* This is purely visual styling - actual positioning must be handled separately with CSS.
*
* All fixed positions shown below for comparison.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line didn't get carried over, but if that's because Claude or someone else decided it wasn't necessary, I could definitely get on board with that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i felt they weren't necessary but that can also be cleaned up in a future docs content review when i look at the guts of our pages more closely.

Comment thread research.md Outdated
* - **Large (`l`)**: Used for prominent displays or primary content areas
* - **Extra-large (`xl`)**: Maximum visibility for high-priority statuses
*
* All sizes shown below for comparison.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is missing from the mdx, but could be considered unneccessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Comment thread 2nd-gen/packages/swc/components/tabs/tabs.mdx Outdated
Comment thread 2nd-gen/packages/swc/components/tabs/tabs.mdx Outdated

Heading is also available in a `--heavy` style that sets the font weight to the heaviest of `black`. Black weight text should only be used in heading type styles, and never below `18px` font-size, to ensure the text remains legible.

<Canvas of={TypographyStories.HeadingHeavy} />

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this other places but I think it's most obvious here: our old stories applied some antialiased font smoothing that the new ones do not. For instance looking at this story:

Previously:
Image

This branch (text looks a little thicker):
Image

Not a blocker, but a possible consideration at some point!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see below

*/
export const Anatomy: Story = {
render: (args) => html`
<h4>Account settings</h4>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, but pointing out that the way plain text is styled is a bit different now, mostly affecting font sizes I think. Here's a side by side comparison (prod on the right):

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there will be some styling fix tickets that we can create. we still havent really reviewed or improved the styles from the garage week project and i know we need to get dark mode working correctly. do you feel like this and the aliasing issue you highlighted might be deferrable to a styling specific task?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure! Just wanted to make sure we were tracking it!

@rise-erpelding rise-erpelding removed their assignment May 29, 2026

@blunteshwar blunteshwar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:
tags is typed as string[] here, but GettingStarted currently declares tags?: string. Runtime is okay because both have .includes(), but the component contracts disagree and this will fail once this path is type-checked more strictly.

Can we update GettingStarted to accept tags?: string[] so the shared docs blocks have a consistent type shape?

Comment thread 2nd-gen/packages/swc/.storybook/blocks/DocsHeader.tsx
@caseyisonit caseyisonit added the High priority PR review PR is a high priority and should be reviewed ASAP label Jun 1, 2026
caseyisonit and others added 2 commits June 1, 2026 08:15
Update GettingStarted's tags prop from `string` to `string[]` so the
type contract matches what DocsHeader passes in. Runtime was already
correct (both call `.includes()`), but the disagreeing types would have
failed under stricter type-checking.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
research.md is generated by the deep-understanding skill as a planning
artifact for the author's own review; it is not project source. Remove
it from this branch and add a gitignore entry so it does not get picked
up by future sessions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`../migration.md` does not resolve from Storybook MDX (the file is
`migration-guide.mdx` and Storybook serves it from a routed path, not
a relative file). Repoint to the Storybook docs URL.

Affects:

- `tabs.mdx` (two links in Directions and States sections), introduced
  by this PR
- `Tab.ts` JSDoc, pre-existing on main
- `tabs.stories.ts` meta JSDoc, pre-existing on main — also rendered
  on the Docs page via `<Description />`

Bundling the three together since they share the same root cause.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@caseyisonit
caseyisonit requested a review from blunteshwar June 1, 2026 14:24

@blunteshwar blunteshwar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@caseyisonit caseyisonit added the Status:Ready for re-review PR has had its feedback addressed and is once again ready for review. label Jun 1, 2026
@caseyisonit
caseyisonit merged commit 5557745 into main Jun 1, 2026
33 checks passed
@caseyisonit
caseyisonit deleted the caseyisonit/docs-to-mdx branch June 1, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component:Documentation Issues or PRs involving changes to docs or docs website. Component prefix is for Jira integration. gen2 These issues or PRs map to our 2nd generation work to modernizing infrastructure. High priority PR review PR is a high priority and should be reviewed ASAP Status:Ready for re-review PR has had its feedback addressed and is once again ready for review. Status:Ready for review PR ready for review or re-review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants