feat(a11y): allow overriding heading tag via as prop on title-bearing components#372
Open
bntvllnt wants to merge 2 commits into
Open
feat(a11y): allow overriding heading tag via as prop on title-bearing components#372bntvllnt wants to merge 2 commits into
as prop on title-bearing components#372bntvllnt wants to merge 2 commits into
Conversation
… components Adds an optional `as` prop (`"h1"`–`"h6"`) to every component that renders a user-supplied title heading, plus per-slot props (`titleAs`, `tocLabelAs`, `sectionLabelAs`) on multi-title components. Defaults preserve current tags so the change is non-breaking. Consumers can now align rendered headings with the surrounding page hierarchy to satisfy WCAG 1.3.1 / 2.4.6 and Lighthouse `heading-order`. Closes #371
bntvllnt
commented
May 19, 2026
Collaborator
Author
bntvllnt
left a comment
There was a problem hiding this comment.
Review — 1 blocking finding
BLOCKING
T1 — PR evidence does not satisfy the issue's Storybook/visual verification acceptance criteria- Evidence: the PR changes 58 files, including 26 component implementations plus registry copies, but no
*.stories.tsx,*.visual.tsx, or snapshot files are changed. The linked issue acceptance criteria require the new heading override to be documented in component TSDoc / Storybook story and require an a11y story or visual test confirming the rendered tag updates. Repodocs/agents/COMPONENTS.mdalso says UI changes should run unit + visual, or explicitly note which visual coverage was skipped and why. - Why it matters: this is an accessibility-facing API across many components. The two Vitest regressions prove the prop works for
FAQandProfileSection, but they do not give Storybook/visual/a11y coverage for the broad component surface that designers and consumers use to verify heading-level behavior. - Fix: add Storybook controls/stories and/or Playwright CT/a11y coverage for the heading override (a representative shared pattern is OK if documented), or update the PR body with a concrete skipped-rationale that explains why Storybook/visual coverage is intentionally not part of this issue.
- Evidence: the PR changes 58 files, including 26 component implementations plus registry copies, but no
VERIFIED CLEAN
- The implementation preserves existing default heading tags in the changed source components I inspected.
HeadingTagis exported from@vllnt/ui, and registry copies import that public type instead of reaching into package internals.- Source and registry changes line up structurally for the affected components.
- Linked issue is present (
Closes #371) and CI checks currently show green ingh pr checks.
VALIDATION
- Ran:
pnpm -F @vllnt/ui exec tsc --noEmit --project tsconfig.build.json— pass. - Ran:
pnpm -F @vllnt/ui lint— pass. - Ran:
pnpm -F @vllnt/ui exec vitest run src/components/faq/faq.test.tsx src/components/profile-section/profile-section.test.tsx— 2 files / 16 tests pass. - Not run locally: full
pnpm buildandpnpm test:once; GitHub checks report green for the PR head.
|
Preview ready · Updated 2026-05-20T14:28:28Z
Inspect
|
bntvllnt
commented
May 20, 2026
Collaborator
Author
bntvllnt
left a comment
There was a problem hiding this comment.
Review — validation pass for heading as prop
BLOCKING
- None found in this pass.
WARN
- None found.
VERIFIED CLEAN
- PR remains non-empty and targets
main:85 files changed, 958 insertions(+), 96 deletions(-)at head396a45727f02061bcc1b72d8970be9e0c6376293. - Issue link is present:
Closes #371. - GitHub reports the PR as open, non-draft, and
CLEANagainstmain. - The PR body is now synced with the current head and includes story/visual validation evidence.
- Source/registry/story coverage shape checks passed locally: 26 changed source component files, 26 changed stories, 26 generated registry copies; every changed HeadingTag source file has the matching registry path; every changed story has the heading-control/override marker.
- Spot-checked story/control and visual coverage:
packages/ui/src/components/profile-section/profile-section.stories.tsxexposes anasselect andHeadingOverridestory.packages/ui/src/components/content-intro/content-intro.stories.tsxexposes per-slottitleAs/tocLabelAscontrols and override story.packages/ui/src/components/heading-overrides.visual.tsxverifies rendered accessible heading levels for representative learning/market/status components.
VALIDATION
Local at 396a45727f02061bcc1b72d8970be9e0c6376293:
pnpm -F @vllnt/ui exec tsx scripts/check-story-coverage.ts→All 236 components have stories.pnpm -F @vllnt/ui exec tsx scripts/verify-stories.ts→Checked: 236 components;All stories provide required props. No crash risks detected.pnpm -F @vllnt/ui exec tsc --noEmit --project tsconfig.build.json→ passed locally.pnpm -F @vllnt/ui exec playwright test -c playwright-ct.config.ts src/components/heading-overrides.visual.tsx→ 2/2 passed.
GitHub checks at the same head are all successful, including Quality Gates, Verify Stories, Storybook, Visual Regression, CodeQL, issue-link enforcement, registry deploy, and preview deploy.
Approval recommended; leaving final APPROVE for the human reviewer per autonomous-review boundary.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
asprop (typed"h1" | "h2" | "h3" | "h4" | "h5" | "h6") to every component that renders a user-supplied title heading. Defaults preserve the current tag → non-breaking.ContentIntro,TutorialComplete) expose per-slot props (titleAs,tocLabelAs,sectionLabelAs) per the issue's "one prop per slot" guidance.HeadingTagfrom@vllnt/uiso consumers (incl. inlined registry copies) can type their callers.ProfileSection) and a default-title-bearing component (FAQ).HeadingOverridestories for the affected components, and adds a Playwright CT coverage file that verifies rendered accessible heading levels for representative learning/market/status components.packages/ui/CHANGELOG.mdunder[Unreleased].Affected components — 24 single-title + 2 multi-title:
ProfileSection,FAQ,Slideshow,WorldClockBar,TableOfContentsPanel,TableOfContents,KeyboardShortcutsHelp,Watchlist,OrderBook,HorizontalScrollRow,MarketTreemap,ActivityHeatmap,Glossary(the heading-bearing component insidekey-concept),StatusBoard,CodePlayground,Comparison,Quiz,Exercise,ShareSection,CompletionDialog,Checklist,LearningObjectives,CandlestickChart,StepByStep,ContentIntro,TutorialComplete.Notes
OrderBook,MarketTreemap,StepByStep), only the primary title is exposed viaas, matching the issue's "oneasprop each" instruction.KeyConceptin the issue scope refers tokey-concept.tsx; the actual heading in that file is on theGlossarycomponent (the<dt>inKeyConceptis not a heading), so the prop is added there.Closes #371
Test plan
pnpm -F @vllnt/ui lint— cleanpnpm -F @vllnt/ui exec tsc --noEmit --project tsconfig.build.json— clean locally at396a45727f02061bcc1b72d8970be9e0c6376293pnpm build— both@vllnt/uiand@vllnt/ui-registrybuild green; registry inlined copies regeneratedpnpm test:once— 216 files / 1215 tests pass, incl. new regression testspnpm -F @vllnt/ui exec tsx scripts/check-story-coverage.ts—All 236 components have stories.pnpm -F @vllnt/ui exec tsx scripts/verify-stories.ts—Checked: 236 components;All stories provide required props. No crash risks detected.pnpm -F @vllnt/ui exec playwright test -c playwright-ct.config.ts src/components/heading-overrides.visual.tsx— 2/2 passed locally at396a45727f02061bcc1b72d8970be9e0c6376293396a45727f02061bcc1b72d8970be9e0c6376293— Quality Gates, Storybook, Visual Regression, CodeQL, issue-link, registry deploy, and preview deploy all successful