diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.tsx
index 6cc7d7cbec99..898f14212517 100644
--- a/packages/x-tree-view/src/TreeItem/TreeItem.tsx
+++ b/packages/x-tree-view/src/TreeItem/TreeItem.tsx
@@ -199,7 +199,7 @@ export const TreeItem = React.forwardRef(function TreeItem(
icons: contextIcons,
runItemPlugins,
items: { disabledItemsFocusable, indentationAtItemLevel },
- selection: { multiSelect },
+ selection: { disableSelection },
expansion: { expansionTrigger },
treeId,
instance,
@@ -358,17 +358,17 @@ export const TreeItem = React.forwardRef(function TreeItem(
});
const icon = Icon ? : null;
- let ariaSelected;
- if (multiSelect) {
- ariaSelected = selected;
- } else if (selected) {
- /* single-selection trees unset aria-selected on un-selected items.
- *
- * If the tree does not support multiple selection, aria-selected
- * is set to true for the selected item and it is not present on any other item in the tree.
- * Source: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
- */
+ // https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
+ let ariaSelected: boolean | undefined;
+ if (selected) {
+ // - each selected node has aria-selected set to true.
ariaSelected = true;
+ } else if (disableSelection || disabled) {
+ // - if the tree contains nodes that are not selectable, aria-selected is not present on those nodes.
+ ariaSelected = undefined;
+ } else {
+ // - all nodes that are selectable but not selected have aria-selected set to false.
+ ariaSelected = false;
}
function handleFocus(event: React.FocusEvent) {
diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx
index 0f80094dc69a..448178c94601 100644
--- a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx
+++ b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx
@@ -712,12 +712,12 @@ describeTreeView<[UseTreeViewSelectionSignature, UseTreeViewExpansionSignature]>
// This `describe` only tests basics scenarios, more complex scenarios are tested in this file's other `describe`.
describe('aria-selected item attribute', () => {
describe('single selection', () => {
- it('should not have the attribute `aria-selected=false` if not selected', () => {
+ it('should have the attribute `aria-selected=false` if not selected', () => {
const view = render({
items: [{ id: '1' }, { id: '2' }],
});
- expect(view.getItemRoot('1')).not.to.have.attribute('aria-selected');
+ expect(view.getItemRoot('1')).to.have.attribute('aria-selected', 'false');
});
it('should have the attribute `aria-selected=true` if selected', () => {
@@ -750,14 +750,23 @@ describeTreeView<[UseTreeViewSelectionSignature, UseTreeViewExpansionSignature]>
expect(view.getItemRoot('1')).to.have.attribute('aria-selected', 'true');
});
- it('should have the attribute `aria-selected=false` if disabledSelection is true', () => {
+ it('should not have the attribute `aria-selected=false` if disabledSelection is true', () => {
const view = render({
multiSelect: true,
items: [{ id: '1' }, { id: '2' }],
disableSelection: true,
});
- expect(view.getItemRoot('1')).to.have.attribute('aria-selected', 'false');
+ expect(view.getItemRoot('1')).not.to.have.attribute('aria-selected');
+ });
+
+ it('should not have the attribute `aria-selected=false` if the item is disabled', () => {
+ const view = render({
+ multiSelect: true,
+ items: [{ id: '1', disabled: true }, { id: '2' }],
+ });
+
+ expect(view.getItemRoot('1')).not.to.have.attribute('aria-selected');
});
});
});
diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts
index a8b8fff491e4..674f7380b39f 100644
--- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts
+++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts
@@ -37,7 +37,7 @@ export const useTreeItem2 = <
const {
runItemPlugins,
items: { onItemClick, disabledItemsFocusable, indentationAtItemLevel },
- selection: { multiSelect, disableSelection, checkboxSelection },
+ selection: { disableSelection, checkboxSelection },
expansion: { expansionTrigger },
treeId,
instance,
@@ -194,17 +194,17 @@ export const useTreeItem2 = <
...extractEventHandlers(externalProps),
};
+ // https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
let ariaSelected: boolean | undefined;
- if (multiSelect) {
- ariaSelected = status.selected;
- } else if (status.selected) {
- /* single-selection trees unset aria-selected on un-selected items.
- *
- * If the tree does not support multiple selection, aria-selected
- * is set to true for the selected item and it is not present on any other item in the tree.
- * Source: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
- */
+ if (status.selected) {
+ // - each selected node has aria-selected set to true.
ariaSelected = true;
+ } else if (disableSelection || status.disabled) {
+ // - if the tree contains nodes that are not selectable, aria-selected is not present on those nodes.
+ ariaSelected = undefined;
+ } else {
+ // - all nodes that are selectable but not selected have aria-selected set to false.
+ ariaSelected = false;
}
const props: UseTreeItem2RootSlotPropsFromUseTreeItem = {