Skip to content

[Stepper] Improve accessibility#47687

Draft
silviuaavram wants to merge 26 commits intomui:masterfrom
silviuaavram:feat/stepper-accessibility
Draft

[Stepper] Improve accessibility#47687
silviuaavram wants to merge 26 commits intomui:masterfrom
silviuaavram:feat/stepper-accessibility

Conversation

@silviuaavram
Copy link
Member

@silviuaavram silviuaavram commented Jan 27, 2026

Fixes #43689.
Fixes #32826.

  • improve markup for stepper and step, from divs to ol and li.
  • implement roving tabindex focus for the step buttons.
  • only export useStepperContext in order to control the usage better.

Technical:

  • roving tabindex has a separate hook that keeps track of the current focusable item (by index).
  • it exports:
    • a keydown handler that is added to the items (step buttons).
    • the focusableIndex in order to only add tabindex 0 to that item only, and -1 to the rest
    • setFocusableIndex in case the user might click on a step, the hook should know to update the current focusable index
    • registerElementRef is called by each step to register its ref to the hook, such that the focus will be done by the keydown
  • focus strategy is left/right arrows in circular movement, while also skipping disabled items.

ToDo: update docs / usages to include the aria-controls attribute, because the step buttons control the showing of content areas.

Copilot AI review requested due to automatic review settings January 27, 2026 08:27
@mui-bot
Copy link

mui-bot commented Jan 27, 2026

Netlify deploy preview

Bundle size report

Bundle Parsed size Gzip size
@mui/material 🔺+429B(+0.08%) 🔺+193B(+0.13%)
@mui/lab 0B(0.00%) 0B(0.00%)
@mui/system 0B(0.00%) 0B(0.00%)
@mui/utils 0B(0.00%) 0B(0.00%)

Details of bundle changes

Generated by 🚫 dangerJS against 353af74

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request improves the accessibility of the Stepper component by implementing semantic HTML markup and keyboard navigation following ARIA best practices.

Changes:

  • Replaced div elements with semantic ol/li elements for Stepper and Step components
  • Implemented roving tabindex focus management with arrow key navigation for step buttons
  • Added ARIA attributes (aria-posinset, aria-setsize, aria-orientation) to improve screen reader support
  • Refactored StepperContext to export only useStepperContext hook and StepperContextProvider, removing the default export

Reviewed changes

Copilot reviewed 13 out of 15 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
packages/mui-material/src/Stepper/utils/useRovingTabIndexFocus.ts New hook implementing circular keyboard navigation with arrow keys, skipping disabled steps
packages/mui-material/src/Stepper/utils/useRovingTabIndexFocus.test.tsx Comprehensive unit tests for the roving tabindex hook
packages/mui-material/src/Stepper/index.js Removed default export of StepperContext, keeping named exports
packages/mui-material/src/Stepper/index.d.ts Updated TypeScript exports to match JavaScript changes
packages/mui-material/src/Stepper/StepperContext.ts Added new context properties for focus management, marked as @internal, exported StepperContextProvider
packages/mui-material/src/Stepper/Stepper.test.tsx Updated test to expect HTMLOListElement instead of HTMLDivElement
packages/mui-material/src/Stepper/Stepper.js Changed root element from div to ol, integrated roving tabindex, added aria-orientation
packages/mui-material/src/StepLabel/StepLabel.js Updated to use useStepperContext hook instead of direct context import
packages/mui-material/src/StepContent/StepContent.js Updated to use useStepperContext hook instead of direct context import
packages/mui-material/src/StepConnector/StepConnector.js Updated to use useStepperContext hook instead of direct context import
packages/mui-material/src/StepButton/StepButton.test.js Added StepperContextProvider wrapper to all test cases
packages/mui-material/src/StepButton/StepButton.js Integrated roving tabindex, added ARIA attributes, implemented keyboard and click handlers
packages/mui-material/src/StepButton/StepButton.d.ts Added TypeScript definitions for onClick and onKeyDown props
packages/mui-material/src/Step/Step.test.js Updated tests for li element and added StepperContextProvider wrappers
packages/mui-material/src/Step/Step.js Changed root element from div to li, updated to use useStepperContext hook

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@silviuaavram silviuaavram marked this pull request as draft January 27, 2026 08:41
@silviuaavram silviuaavram force-pushed the feat/stepper-accessibility branch from 2efcaec to a84bfad Compare January 27, 2026 17:44
@silviuaavram silviuaavram marked this pull request as ready for review January 27, 2026 17:56
@zannager zannager added the scope: stepper Changes related to the stepper. label Jan 29, 2026
@zannager zannager requested a review from mj12albert January 29, 2026 16:15
Copy link
Member

@ZeeshanTamboli ZeeshanTamboli left a comment

Choose a reason for hiding this comment

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

@silviuaavram Tested it initially with NVDA screen reader. Nice improvements.

  1. With NVDA enabled, the Left/Right arrow keys don't work on the non-linear stepper:
    https://deploy-preview-47687--material-ui.netlify.app/material-ui/react-stepper/#non-linear and nothing is announced as well. When NVDA is off, arrow-key navigation works as expected.
  2. Is it expected that Tab key should move focus to the next step? Since this isn't a tablist, I'm not sure. On the docs site (https://mui.com/material-ui/react-stepper/#non-linear), Tab moves between steps, but in this PR it jumps directly to the "Next" button.
  3. If useStepperContext is intended to be a public API, I think we should document how to use it with a custom stepper demo.

@ZeeshanTamboli ZeeshanTamboli added accessibility a11y type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. labels Jan 31, 2026
@silviuaavram
Copy link
Member Author

silviuaavram commented Feb 2, 2026

Hey @ZeeshanTamboli thanks for your input!

  1. I don't know what to say, especially that I don't have a windows setup at the moment. For example, does this stepper work with NVDA?
  2. I expect Tab to only work on one step at a time. Focusing other steppers with keyboard should work with arrows instead.
  3. useStepperContext should not be public, as StepperContext wasn't public either, right? The hook is meant be used internally, instead of doing useContext(StepperContext).

@ZeeshanTamboli
Copy link
Member

Hey @ZeeshanTamboli thanks for your input!

  1. I don't know what to say, especially that I don't have a windows setup at the moment. For example, does this stepper work with NVDA?

Yes, it works. I am able to navigate with left/right arrow keys with NVDA enabled in this demo but not in this PR's demo.

  1. I expect Tab to only work on one step at a time. Focusing other steppers with keyboard should work with arrows instead.

Ok, so you mean, pressing Tab should focus only on the last focused step in the Stepper and not move to the next step like in production?

  1. useStepperContext should not be public, as StepperContext wasn't public either, right? The hook is meant be used internally, instead of doing useContext(StepperContext).

I read this only export useStepperContext in order to control the usage better. in the PR description, so I thought it is exported.

@silviuaavram silviuaavram force-pushed the feat/stepper-accessibility branch from d598657 to be10951 Compare February 10, 2026 13:38
@silviuaavram silviuaavram marked this pull request as draft February 18, 2026 09:10
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Feb 19, 2026
@silviuaavram silviuaavram force-pushed the feat/stepper-accessibility branch from 1f0ac0d to 353af74 Compare February 19, 2026 14:50
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accessibility a11y scope: stepper Changes related to the stepper. type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Stepper] Lacks accessibility Accessibility | Narrator is not announcing the Stepper headings as "selected"

6 participants

Comments