Skip to content

Commit fc90cb8

Browse files
committed
fix(aria/combobox): handle unselectable tree items
1 parent 8301b8b commit fc90cb8

File tree

5 files changed

+36
-3
lines changed

5 files changed

+36
-3
lines changed

src/aria/private/combobox/combobox.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,19 @@ export interface ComboboxTreeControls<T extends ListItem<V>, V>
101101
collapseItem: () => void;
102102

103103
/** Checks if the currently active item in the popup is expandable. */
104-
isItemExpandable: () => boolean;
104+
isItemExpandable: (item?: T) => boolean;
105105

106106
/** Expands all nodes in the tree. */
107107
expandAll: () => void;
108108

109109
/** Collapses all nodes in the tree. */
110110
collapseAll: () => void;
111+
112+
/** Toggles the expansion state of the currently active item in the popup. */
113+
toggleExpansion: (item?: T) => void;
114+
115+
/** Whether the current active item is selectable. */
116+
isItemSelectable: (item?: T) => boolean;
111117
}
112118

113119
/** Controls the state of a combobox. */
@@ -175,16 +181,25 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
175181
.on('ArrowUp', () => this.prev())
176182
.on('Home', () => this.first())
177183
.on('End', () => this.last())
178-
.on('Escape', () => this.close({reset: true}))
179-
.on('Enter', () => this.select({commit: true, close: true}));
184+
.on('Escape', () => this.close({reset: true}));
180185

181186
if (this.readonly()) {
182187
manager.on(' ', () => this.select({commit: true, close: true}));
183188
}
184189

190+
if (popupControls.role() === 'listbox') {
191+
manager.on('Enter', () => this.select({commit: true, close: true}));
192+
}
193+
185194
if (popupControls.role() === 'tree') {
186195
const treeControls = popupControls as ComboboxTreeControls<T, V>;
187196

197+
if (treeControls.isItemSelectable()) {
198+
manager.on('Enter', () => this.select({commit: true, close: true}));
199+
} else if (treeControls.isItemExpandable()) {
200+
manager.on('Enter', () => this.expandItem());
201+
}
202+
188203
if (treeControls.isItemExpandable() || treeControls.isItemCollapsible()) {
189204
manager.on(this.collapseKey(), () => this.collapseItem());
190205
}
@@ -203,6 +218,16 @@ export class ComboboxPattern<T extends ListItem<V>, V> {
203218
const item = this.inputs.popupControls()?.getItem(e);
204219

205220
if (item) {
221+
if (this.inputs.popupControls()?.role() === 'tree') {
222+
const treeControls = this.inputs.popupControls() as ComboboxTreeControls<T, V>;
223+
224+
if (treeControls.isItemExpandable(item) && !treeControls.isItemSelectable(item)) {
225+
treeControls.toggleExpansion(item);
226+
this.inputs.inputEl()?.focus();
227+
return;
228+
}
229+
}
230+
206231
this.select({item, commit: true, close: true});
207232
this.inputs.inputEl()?.focus(); // Return focus to the input after selecting.
208233
}

src/aria/private/tree/combobox-tree.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,9 @@ export class ComboboxTreePattern<V>
104104

105105
/** Collapses all of the tree items. */
106106
collapseAll = () => this.items().forEach(item => item.expansion.close());
107+
108+
/** Whether the currently active item is selectable. */
109+
isItemSelectable = (item: TreeItemPattern<V> | undefined = this.inputs.activeItem()) => {
110+
return item ? item.selectable() : false;
111+
};
107112
}

src/components-examples/aria/combobox/combobox-tree-auto-select/combobox-tree-auto-select-example.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
[parent]="parent"
3535
[value]="node.name"
3636
[label]="node.name"
37+
[selectable]="!node.children"
3738
#treeItem="ngTreeItem"
3839
class="example-tree-item example-selectable example-stateful"
3940
>

src/components-examples/aria/combobox/combobox-tree-highlight/combobox-tree-highlight-example.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
[parent]="parent"
3535
[value]="node.name"
3636
[label]="node.name"
37+
[selectable]="!node.children"
3738
#treeItem="ngTreeItem"
3839
class="example-tree-item example-selectable example-stateful"
3940
>

src/components-examples/aria/combobox/combobox-tree-manual/combobox-tree-manual-example.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
[parent]="parent"
3535
[value]="node.name"
3636
[label]="node.name"
37+
[selectable]="!node.children"
3738
#treeItem="ngTreeItem"
3839
class="example-tree-item example-selectable example-stateful"
3940
>

0 commit comments

Comments
 (0)