Skip to content

feat(Accordion): add headingLevel prop so consumers can set the correct aria-level for item headings#3367

Open
starboyvarun wants to merge 1 commit intorazorpay:masterfrom
starboyvarun:fix/accordion-configurable-heading-level
Open

feat(Accordion): add headingLevel prop so consumers can set the correct aria-level for item headings#3367
starboyvarun wants to merge 1 commit intorazorpay:masterfrom
starboyvarun:fix/accordion-configurable-heading-level

Conversation

@starboyvarun
Copy link
Copy Markdown

Summary

Every AccordionItem trigger renders inside a heading wrapper. The heading level was hardcoded to 3:

// AccordionButton.web.tsx (before)
<BaseBox
  // a11y guidelines suggest having an apt heading surround a button but heading level is hardcoded here
  {...makeAccessible({ role: 'heading', level: 3 })}
  width="100%"
>

This means every accordion — regardless of where it sits in the page — always announces as an <h3>. If an accordion lives inside an <h1> section, screen readers encounter heading levels that jump from 1 → 3 (skipping 2), which breaks document outline navigation. If it lives inside an <h4> section, the <h3> is actually higher in the hierarchy than its parent.

The comment in the code acknowledged this: // a11y guidelines suggest having an apt heading surround a button but heading level is hardcoded here.

Fix

Added headingLevel?: 1 | 2 | 3 | 4 | 5 | 6 to AccordionProps (defaults to 3). The value flows through AccordionContext to AccordionButton.web.tsx.

// Usage
<Accordion headingLevel={2}>
  <AccordionItem>...</AccordionItem>
</Accordion>
// AccordionButton.web.tsx (after)
<BaseBox
  {...makeAccessible({ role: 'heading', level: headingLevel })}
  width="100%"
>

The default value is 3, so existing consumers are completely unaffected.

Changes

  • types.ts — add headingLevel?: 1 | 2 | 3 | 4 | 5 | 6 to AccordionProps with JSDoc
  • AccordionContext.tsx — add headingLevel to AccordionContextState
  • Accordion.tsx — destructure headingLevel = 3, include in context value and useMemo deps
  • AccordionButton.web.tsx — read headingLevel from context, replace hardcoded 3, remove stale comment

Testing

  • Default: accordion without headingLevel prop still renders aria-level="3" (unchanged)
  • Custom: <Accordion headingLevel={2}> renders aria-level="2" on each item's heading wrapper
  • Screen reader (NVDA/VoiceOver): document outline navigation follows the specified heading level correctly

…m headings

Each AccordionItem's trigger was wrapped in a heading with a hardcoded
aria-level="3". This meant the heading was always announced as an h3
regardless of where the Accordion appeared in the document, which breaks
screen reader navigation when the accordion lives inside an h1 or h4 section.

Added a headingLevel prop (1-6, default 3) to Accordion. The value flows
through AccordionContext to AccordionButton.web.tsx, replacing the hardcoded
3. Existing consumers are unaffected since the default remains 3.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 2, 2026

🦋 Changeset detected

Latest commit: 1a294d3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@razorpay/blade Minor

Not sure what this means? Click here to learn what changesets are.

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 2, 2026

✅ PR title follows Conventional Commits specification.

@codesandbox-ci
Copy link
Copy Markdown

codesandbox-ci Bot commented May 2, 2026

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 1a294d3:

Sandbox Source
razorpay/blade: basic Configuration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant