Skip to content

Commit 60ed032

Browse files
authored
docs(aria/combobox): add no results when there are no results from filtering (#33188)
1 parent 306fe00 commit 60ed032

9 files changed

Lines changed: 161 additions & 64 deletions

File tree

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,28 @@
55
[(value)]="searchString" [(expanded)]="popupExpanded" (click)="popupExpanded.set(true)" />
66
</div>
77

8+
<div aria-live="polite" class="cdk-visually-hidden">
9+
{{options().length === 0 ? 'No results found for ' + searchString() : ''}}
10+
</div>
11+
812
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}" [cdkConnectedOverlayOpen]="true"
913
[cdkConnectedOverlayDisableClose]="true">
1014
<ng-template ngComboboxPopup [combobox]="combobox">
11-
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox example-popup" focusMode="activedescendant"
15+
<div class="example-popup">
16+
@if (options().length === 0) {
17+
<div class="example-no-results">No results found</div>
18+
}
19+
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox" focusMode="activedescendant"
1220
[tabindex]="-1" [(value)]="selectedOption" (click)="onCommit()" (keydown.enter)="onCommit()"
13-
[activeDescendant]="listbox.activeDescendant()">
21+
[activeDescendant]="listbox.activeDescendant()"
22+
[class.example-empty]="options().length === 0">
1423
@for (option of options(); track option) {
1524
<div class="example-option example-selectable example-stateful" ngOption [value]="option" [label]="option">
1625
<span>{{option}}</span>
1726
<span aria-hidden="true" class="material-symbols-outlined example-icon example-selected-icon">check</span>
1827
</div>
1928
}
29+
</div>
2030
</div>
2131
</ng-template>
2232
</ng-template>

src/components-examples/aria/simple-combobox/simple-combobox-dialog/simple-combobox-dialog-example.html

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,29 @@
1818
placeholder="Search..." [(ngModel)]="searchString" [alwaysExpanded]="true"
1919
(keydown.escape)="onSearchEscape($event)" />
2020
</div>
21+
22+
<div aria-live="polite" class="cdk-visually-hidden">
23+
{{options().length === 0 ? 'No results found for ' + searchString() : ''}}
24+
</div>
25+
2126
<ng-template ngComboboxPopup [combobox]="innerCombobox">
22-
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox" focusMode="activedescendant"
23-
tabindex="-1" selectionMode="explicit" [(value)]="selectedStates" (click)="onCommit()"
24-
(keydown.enter)="onCommit()" [activeDescendant]="listbox.activeDescendant()">
25-
@for (option of options(); track option) {
26-
<div class="example-option example-selectable example-stateful" ngOption [value]="option"
27-
[label]="option">
28-
<span>{{option}}</span>
29-
<span aria-hidden="true"
30-
class="material-symbols-outlined example-icon example-selected-icon">check</span>
31-
</div>
27+
<div class="example-popup example-popup-no-margin">
28+
@if (options().length === 0) {
29+
<div class="example-no-results">No results found</div>
3230
}
31+
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox" focusMode="activedescendant"
32+
tabindex="-1" selectionMode="explicit" [(value)]="selectedStates" (click)="onCommit()"
33+
(keydown.enter)="onCommit()" [activeDescendant]="listbox.activeDescendant()"
34+
[class.example-empty]="options().length === 0">
35+
@for (option of options(); track option) {
36+
<div class="example-option example-selectable example-stateful" ngOption [value]="option"
37+
[label]="option">
38+
<span>{{option}}</span>
39+
<span aria-hidden="true"
40+
class="material-symbols-outlined example-icon example-selected-icon">check</span>
41+
</div>
42+
}
43+
</div>
3344
</div>
3445
</ng-template>
3546
</div>

src/components-examples/aria/simple-combobox/simple-combobox-example.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,20 @@ ul[role='group'] {
360360
.example-grid-row[aria-selected='true'] .example-selected-icon {
361361
visibility: visible;
362362
}
363+
364+
.example-no-results {
365+
padding: 1rem;
366+
}
367+
368+
.example-empty {
369+
position: absolute;
370+
visibility: hidden;
371+
pointer-events: none;
372+
height: 0;
373+
width: 0;
374+
overflow: hidden;
375+
}
376+
377+
.example-popup-no-margin {
378+
margin-block-start: 0;
379+
}

src/components-examples/aria/simple-combobox/simple-combobox-grid/simple-combobox-grid-example.html

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,38 @@
55
[(value)]="searchString" [(expanded)]="popupExpanded" (blur)="onBlur()" (click)="popupExpanded.set(true)" />
66
</div>
77

8+
<div aria-live="polite" class="cdk-visually-hidden">
9+
{{filteredItems().length === 0 ? 'No results found for ' + searchString() : ''}}
10+
</div>
11+
812
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}" [cdkConnectedOverlayOpen]="true"
913
[cdkConnectedOverlayDisableClose]="true">
1014
<ng-template ngComboboxPopup [combobox]="combobox">
11-
<div ngComboboxWidget ngGrid focusMode="activedescendant" [tabindex]="-1" class="example-popup"
12-
colWrap="continuous" #grid="ngGrid" [activeDescendant]="grid.activeDescendant()">
13-
@for (item of filteredItems(); track item.label; let i = $index) {
14-
<div ngGridRow class="example-grid-row" [attr.aria-selected]="item === selectedItem()">
15-
<div ngGridCell [id]="item.label + '-label'" [rowIndex]="i" [colIndex]="0"
16-
class="example-cell-label example-cell" (activated)="selectItem(item)">
17-
<button ngGridCellWidget class="example-label-button example-no-active-outline" (click)="selectItem(item)">
18-
{{item.label}}
19-
</button>
20-
<mat-icon class="example-selected-icon">check</mat-icon>
21-
</div>
22-
<div ngGridCell [id]="item.label + '-delete'" [rowIndex]="i" [colIndex]="1"
23-
class="example-cell-button example-cell " (activated)="removeItem(item)">
24-
<button ngGridCellWidget class="example-button example-no-active-outline" (click)="removeItem(item)"
25-
(pointerdown)="$event.preventDefault()">
26-
<mat-icon>close</mat-icon>
27-
</button>
15+
<div class="example-popup">
16+
@if (filteredItems().length === 0) {
17+
<div class="example-no-results">No results found</div>
18+
}
19+
<div ngComboboxWidget ngGrid focusMode="activedescendant" [tabindex]="-1"
20+
colWrap="continuous" #grid="ngGrid" [activeDescendant]="grid.activeDescendant()">
21+
@for (item of filteredItems(); track item.label; let i = $index) {
22+
<div ngGridRow class="example-grid-row" [attr.aria-selected]="item === selectedItem()">
23+
<div ngGridCell [id]="item.label + '-label'" [rowIndex]="i" [colIndex]="0"
24+
class="example-cell-label example-cell" (activated)="selectItem(item)">
25+
<button ngGridCellWidget class="example-label-button example-no-active-outline" (click)="selectItem(item)">
26+
{{item.label}}
27+
</button>
28+
<mat-icon class="example-selected-icon">check</mat-icon>
29+
</div>
30+
<div ngGridCell [id]="item.label + '-delete'" [rowIndex]="i" [colIndex]="1"
31+
class="example-cell-button example-cell " (activated)="removeItem(item)">
32+
<button ngGridCellWidget class="example-button example-no-active-outline" (click)="removeItem(item)"
33+
(pointerdown)="$event.preventDefault()">
34+
<mat-icon>close</mat-icon>
35+
</button>
36+
</div>
2837
</div>
38+
}
2939
</div>
30-
}
3140
</div>
3241
</ng-template>
3342
</ng-template>

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,29 @@
77
[inlineSuggestion]="(searchString() || navigated()) ? selectedOption()[0] : undefined" />
88
</div>
99

10+
<div aria-live="polite" class="cdk-visually-hidden">
11+
{{options().length === 0 ? 'No results found for ' + searchString() : ''}}
12+
</div>
13+
1014
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}" [cdkConnectedOverlayOpen]="true"
1115
[cdkConnectedOverlayDisableClose]="true">
1216
<ng-template ngComboboxPopup [combobox]="combobox">
13-
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox example-popup"
14-
focusMode="activedescendant" [tabindex]="-1" [(value)]="selectedOption" (click)="onCommit()"
15-
(keydown.enter)="onCommit()" [activeDescendant]="listbox.activeDescendant()">
16-
@for (option of options(); track option.name) {
17-
<div class="example-option example-selectable example-stateful" ngOption [value]="option.name"
18-
[label]="option.name" [disabled]="option.disabled">
19-
<span>{{option.name}}</span>
20-
<span aria-hidden="true" class="material-symbols-outlined example-icon example-selected-icon">check</span>
21-
</div>
17+
<div class="example-popup">
18+
@if (options().length === 0) {
19+
<div class="example-no-results">No results found</div>
2220
}
21+
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox"
22+
focusMode="activedescendant" [tabindex]="-1" [(value)]="selectedOption" (click)="onCommit()"
23+
(keydown.enter)="onCommit()" [activeDescendant]="listbox.activeDescendant()"
24+
[class.example-empty]="options().length === 0">
25+
@for (option of options(); track option.name) {
26+
<div class="example-option example-selectable example-stateful" ngOption [value]="option.name"
27+
[label]="option.name" [disabled]="option.disabled">
28+
<span>{{option.name}}</span>
29+
<span aria-hidden="true" class="material-symbols-outlined example-icon example-selected-icon">check</span>
30+
</div>
31+
}
32+
</div>
2333
</div>
2434
</ng-template>
2535
</ng-template>

src/components-examples/aria/simple-combobox/simple-combobox-listbox/simple-combobox-listbox-example.html

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,28 @@
55
[(value)]="searchString" [(expanded)]="popupExpanded" (click)="popupExpanded.set(true)" />
66
</div>
77

8+
<div aria-live="polite" class="cdk-visually-hidden">
9+
{{options().length === 0 ? 'No results found for ' + searchString() : ''}}
10+
</div>
11+
812
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}" [cdkConnectedOverlayOpen]="true"
913
[cdkConnectedOverlayDisableClose]="true">
1014
<ng-template ngComboboxPopup [combobox]="combobox">
11-
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox example-popup" focusMode="activedescendant"
12-
[tabindex]="-1" selectionMode="explicit" [(value)]="selectedOption" (click)="onCommit()"
13-
(keydown.enter)="onCommit()" [activeDescendant]="listbox.activeDescendant()">
14-
@for (option of options(); track option) {
15-
<div class="example-option example-selectable example-stateful" ngOption [value]="option" [label]="option">
16-
<span>{{option}}</span>
17-
<span aria-hidden="true" class="material-symbols-outlined example-icon example-selected-icon">check</span>
18-
</div>
15+
<div class="example-popup">
16+
@if (options().length === 0) {
17+
<div class="example-no-results">No results found</div>
1918
}
19+
<div #listbox="ngListbox" ngListbox ngComboboxWidget class="example-listbox" focusMode="activedescendant"
20+
[tabindex]="-1" selectionMode="explicit" [(value)]="selectedOption" (click)="onCommit()"
21+
(keydown.enter)="onCommit()" [activeDescendant]="listbox.activeDescendant()"
22+
[class.example-empty]="options().length === 0">
23+
@for (option of options(); track option) {
24+
<div class="example-option example-selectable example-stateful" ngOption [value]="option" [label]="option">
25+
<span>{{option}}</span>
26+
<span aria-hidden="true" class="material-symbols-outlined example-icon example-selected-icon">check</span>
27+
</div>
28+
}
29+
</div>
2030
</div>
2131
</ng-template>
2232
</ng-template>

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,25 @@
55
[(value)]="searchString" [(expanded)]="popupExpanded" (click)="popupExpanded.set(true)" />
66
</div>
77

8+
<div aria-live="polite" class="cdk-visually-hidden">
9+
{{filteredGroups().length === 0 ? 'No results found for ' + searchString() : ''}}
10+
</div>
11+
812
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}"
913
[cdkConnectedOverlayOpen]="popupExpanded()" [cdkConnectedOverlayDisableClose]="true">
1014
<ng-template ngComboboxPopup [combobox]="combobox" popupType="tree">
11-
<ul ngTree ngComboboxWidget class="example-tree example-popup" focusMode="activedescendant" [tabindex]="-1"
12-
selectionMode="follow" [(value)]="selectedValues" (click)="onCommit()" (keydown.enter)="onCommit()"
13-
#tree="ngTree" [activeDescendant]="tree.activeDescendant()">
14-
<ng-template [ngTemplateOutlet]="treeNodes"
15-
[ngTemplateOutletContext]="{nodes: filteredGroups(), parent: tree}" />
16-
</ul>
15+
<div class="example-popup">
16+
@if (filteredGroups().length === 0) {
17+
<div class="example-no-results">No results found</div>
18+
}
19+
<ul ngTree ngComboboxWidget class="example-tree" focusMode="activedescendant" [tabindex="-1"
20+
selectionMode="follow" [(value)]="selectedValues" (click)="onCommit()" (keydown.enter)="onCommit()"
21+
#tree="ngTree" [activeDescendant]="tree.activeDescendant()"
22+
[class.example-empty]="filteredGroups().length === 0">
23+
<ng-template [ngTemplateOutlet]="treeNodes"
24+
[ngTemplateOutletContext]="{nodes: filteredGroups(), parent: tree}" />
25+
</ul>
26+
</div>
1727
</ng-template>
1828
</ng-template>
1929
</div>

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,25 @@
77
[inlineSuggestion]="(searchString() || navigated()) ? selectedValues()[0] : undefined" />
88
</div>
99

10+
<div aria-live="polite" class="cdk-visually-hidden">
11+
{{filteredGroups().length === 0 ? 'No results found for ' + searchString() : ''}}
12+
</div>
13+
1014
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}" [cdkConnectedOverlayOpen]="true"
1115
[cdkConnectedOverlayDisableClose]="true">
1216
<ng-template ngComboboxPopup [combobox]="combobox" popupType="tree">
13-
<ul ngTree ngComboboxWidget class="example-tree example-popup" focusMode="activedescendant" [tabindex]="-1"
14-
selectionMode="follow" [(value)]="selectedValues" (click)="onCommit()" (keydown.enter)="onCommit()"
15-
#tree="ngTree" [activeDescendant]="tree.activeDescendant()">
16-
<ng-template [ngTemplateOutlet]="treeNodes"
17-
[ngTemplateOutletContext]="{nodes: filteredGroups(), parent: tree}" />
18-
</ul>
17+
<div class="example-popup">
18+
@if (filteredGroups().length === 0) {
19+
<div class="example-no-results">No results found</div>
20+
}
21+
<ul ngTree ngComboboxWidget class="example-tree" focusMode="activedescendant" [tabindex]="-1"
22+
selectionMode="follow" [(value)]="selectedValues" (click)="onCommit()" (keydown.enter)="onCommit()"
23+
#tree="ngTree" [activeDescendant]="tree.activeDescendant()"
24+
[class.example-empty]="filteredGroups().length === 0">
25+
<ng-template [ngTemplateOutlet]="treeNodes"
26+
[ngTemplateOutletContext]="{nodes: filteredGroups(), parent: tree}" />
27+
</ul>
28+
</div>
1929
</ng-template>
2030
</ng-template>
2131
</div>

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,24 @@
55
[(expanded)]="popupExpanded" (click)="popupExpanded.set(true)" />
66
</div>
77

8+
<div aria-live="polite" class="cdk-visually-hidden">
9+
{{filteredGroups().length === 0 ? 'No results found for ' + searchString() : ''}}
10+
</div>
11+
812
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}"
913
[cdkConnectedOverlayOpen]="popupExpanded()" [cdkConnectedOverlayDisableClose]="true">
1014
<ng-template ngComboboxPopup [combobox]="combobox" popupType="tree">
11-
<ul ngTree ngComboboxWidget class="example-tree example-popup" focusMode="activedescendant" [tabindex]="-1"
12-
selectionMode="explicit" [(value)]="selectedValues" (click)="onCommit()" (keydown.enter)="onCommit()" #tree="ngTree"
13-
[activeDescendant]="tree.activeDescendant()">
14-
<ng-template [ngTemplateOutlet]="treeNodes" [ngTemplateOutletContext]="{nodes: filteredGroups(), parent: tree}" />
15-
</ul>
15+
<div class="example-popup">
16+
@if (filteredGroups().length === 0) {
17+
<div class="example-no-results">No results found</div>
18+
}
19+
<ul ngTree ngComboboxWidget class="example-tree" focusMode="activedescendant" [tabindex]="-1"
20+
selectionMode="explicit" [(value)]="selectedValues" (click)="onCommit()" (keydown.enter)="onCommit()" #tree="ngTree"
21+
[activeDescendant]="tree.activeDescendant()"
22+
[class.example-empty]="filteredGroups().length === 0">
23+
<ng-template [ngTemplateOutlet]="treeNodes" [ngTemplateOutletContext]="{nodes: filteredGroups(), parent: tree}" />
24+
</ul>
25+
</div>
1626
</ng-template>
1727
</ng-template>
1828
</div>

0 commit comments

Comments
 (0)