Skip to content

[tree view] Use aria-selected instead of aria-checked when checkboxSelection is disabled - #23679

Merged
michelengelen merged 2 commits into
mui:masterfrom
michelengelen:bugfix/23667-tree-view-aria-selected
Sep 25, 2026
Merged

michelengelen merged 2 commits into
mui:masterfrom
michelengelen:bugfix/23667-tree-view-aria-selected

Conversation

@michelengelen

Copy link
Copy Markdown
Member

SimpleTreeView and RichTreeView set aria-checked on every selectable item regardless of whether checkboxSelection was enabled, and never set aria-selected. Per the ARIA APG treeview pattern, aria-checked belongs to the checkbox variant of the widget; a plain selection tree should convey the selected item through aria-selected instead. As a result, a single-select navigation tree with no checkboxes announced every unselected row as "not checked", describing an interaction the widget didn't actually offer.

itemPlugin.ts's root props enhancer now branches on isCheckboxSelectionEnabled: when checkboxes are enabled, behavior is unchanged (aria-checked with true/false/"mixed"); when they are not, the item emits aria-selected (true/false, or omitted for disabled/non-selectable items) instead. aria-selected has no tri-state value, so a parent with only some descendants selected (the previous "mixed" case) is now reported as not selected, since that partial state only has meaning in the checkbox variant.

The isItemSelected/getSelectedTreeItems test helpers in describeTreeView.tsx read aria-checked directly and are used at 70+ call sites across the suite, so they were updated to check both attributes. The dedicated aria-checked test block was split into "without checkboxSelection" (asserting aria-selected) and "with checkboxSelection" (asserting aria-checked, unchanged), and a couple of standalone assertions elsewhere that exercised the no-checkbox case were updated to match.

Fixes #23667

@michelengelen michelengelen self-assigned this Sep 23, 2026
@michelengelen michelengelen 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. scope: tree view Changes related to the tree view. This includes TreeView, TreeItem. labels Sep 23, 2026
@code-infra-dashboard

code-infra-dashboard Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Deploy preview

https://deploy-preview-23679--material-ui-x.netlify.app/
QR code for https://deploy-preview-23679--material-ui-x.netlify.app/

Bundle size

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-charts-premium 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 🔺+115B(+0.15%) 🔺+37B(+0.17%)
@mui/x-tree-view-pro 🔺+115B(+0.08%) 🔺+37B(+0.09%)
@mui/x-scheduler 🔺+115B(+0.03%) 🔺+33B(+0.03%)
@mui/x-scheduler-premium 🔺+115B(+0.02%) 🔺+32B(+0.02%)
@mui/x-chat 0B(0.00%) 0B(0.00%)
@mui/x-license 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@LukasTy LukasTy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Claude Opus findings

The fix direction is correct, but the new aria-selected branch has one bug: it reads the derived selection status, not the selection model.

  • aria-selected does not follow the selection model (packages/x-tree-view/src/internals/plugins/selection/itemPlugin.ts:39). The branch without checkboxes uses selectionStatus === 'selected'. With selectionPropagation.parents, that status is 'selected' for a parent when all its selectable children are selected, also when the parent is not in selectedItems. The highlight (data-selected) uses the model. I checked two cases in jsdom:
    • multiSelect, selectionPropagation={{ parents: true }}, defaultSelectedItems={['1.1', '1.2']}: item 1 has aria-selected="true" and no highlight. Press Space on 1 two times: the highlight turns on and off, but aria-selected stays "true".
    • Single select, selectionPropagation={{ parents: true }}, defaultSelectedItems="1.1" (the only child of 1): 1 and 1.1 both have aria-selected="true", and the tree has aria-multiselectable="false".
    • Fix: use selectionSelectors.isItemSelected in this branch, like the aria-selected code before #19851 (status.selected). With this change, both cases match the highlight, and all x-tree-view and x-tree-view-pro unit tests pass. Please add a test for these cases. Base has the same problem with aria-checked, but this PR defines the new aria-selected behavior.
  • Duplicated decision chain (itemPlugin.ts:35-76). The new branch repeats the checkbox chain. Keep one chain and change only the output: isCheckboxSelectionEnabled ? { 'aria-checked': value, 'aria-selected': undefined } : { 'aria-checked': undefined, 'aria-selected': value === 'mixed' ? false : value }. Then the not-selectable rules from #23012 stay in one place. With the fix above, the "selected" step reads isItemSelected when checkboxes are off.
  • PR title. The title becomes the changelog line. The 8.17.0 line was "Use aria-checked instead of aria-selected on items" (#19851), and a user reported there that it broke their Playwright locators ({ selected: true } to { checked: true }). Suggestion: "[tree view] Use aria-selected instead of aria-checked when checkboxSelection is disabled".

@michelengelen michelengelen changed the title [tree view] Only use aria-checked when checkboxSelection is enabled "[tree view] Use aria-selected instead of aria-checked when checkboxSelection is disabled Sep 25, 2026
@LukasTy LukasTy changed the title "[tree view] Use aria-selected instead of aria-checked when checkboxSelection is disabled [tree view] Use aria-selected instead of aria-checked when checkboxSelection is disabled Sep 25, 2026

@LukasTy LukasTy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. 👍

@michelengelen
michelengelen merged commit ba99ac8 into mui:master Sep 25, 2026
23 checks passed
@michelengelen
michelengelen deleted the bugfix/23667-tree-view-aria-selected branch September 28, 2026 06:57
unhappychoice added a commit to unhappychoice/mdts that referenced this pull request Oct 18, 2026
MUI X 9.15 conveys tree item selection via aria-selected instead of
aria-checked when checkboxSelection is disabled (mui/mui-x#23679).
Update the affected LeftPane snapshots accordingly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accessibility a11y scope: tree view Changes related to the tree view. This includes TreeView, TreeItem. 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.

[tree view] SimpleTreeView sets aria-checked on single-select trees and never sets aria-selected

2 participants