Skip to content

Commit e446fbd

Browse files
committed
docs(aria/combobox): multi select examples
1 parent d458f5d commit e446fbd

File tree

8 files changed

+183
-46
lines changed

8 files changed

+183
-46
lines changed

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

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
.example-combobox-container {
22
position: relative;
3-
width: 300px;
3+
width: 100%;
44
display: flex;
55
flex-direction: column;
66
border: 1px solid var(--mat-sys-outline);
77
border-radius: var(--mat-sys-corner-extra-small);
88
}
99

10+
.example-combobox-container:has([readonly='true']) {
11+
width: 200px;
12+
}
13+
1014
.example-combobox-input-container {
1115
display: flex;
1216
position: relative;
@@ -78,6 +82,7 @@
7882
overflow: auto;
7983
max-height: 10rem;
8084
padding: 0.5rem;
85+
gap: 4px;
8186
}
8287

8388
.example-option {
@@ -89,6 +94,26 @@
8994
flex-shrink: 0;
9095
align-items: center;
9196
justify-content: space-between;
97+
gap: 1rem;
98+
}
99+
100+
.example-option-text {
101+
flex: 1;
102+
}
103+
104+
.example-checkbox-blank-icon,
105+
.example-option[aria-selected='true'] .example-checkbox-filled-icon {
106+
display: flex;
107+
align-items: center;
108+
}
109+
110+
.example-checkbox-filled-icon,
111+
.example-option[aria-selected='true'] .example-checkbox-blank-icon {
112+
display: none;
113+
}
114+
115+
.example-checkbox-blank-icon {
116+
opacity: 0.6;
92117
}
93118

94119
.example-selected-icon {
@@ -99,26 +124,17 @@
99124
visibility: visible;
100125
}
101126

102-
.example-option[inert],
103-
.example-tree-item[inert] {
104-
display: none;
127+
.example-option[aria-selected='true'] {
128+
color: var(--mat-sys-primary);
129+
background-color: color-mix(in srgb, var(--mat-sys-primary) 10%, transparent);
130+
}
131+
132+
.example-option:hover {
133+
background-color: color-mix(in srgb, var(--mat-sys-on-surface) 10%, transparent);
105134
}
106135

107136
.example-combobox-container:focus-within [data-active='true'] {
108-
background: color-mix(
109-
in srgb,
110-
var(--mat-sys-on-surface) calc(var(--mat-sys-focus-state-layer-opacity) * 100%),
111-
transparent
112-
);
113-
}
114-
115-
.example-combobox-container:focus-within [data-active='true'][aria-selected='true'] {
116-
background: color-mix(
117-
in srgb,
118-
var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%),
119-
transparent
120-
);
121-
color: var(--mat-sys-primary);
137+
outline: 2px solid color-mix(in srgb, var(--mat-sys-primary) 80%, transparent);
122138
}
123139

124140
.example-tree {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<div ngCombobox #combobox="ngCombobox" class="example-combobox-container" [readonly]="true">
2+
<div class="example-combobox-input-container">
3+
<input
4+
ngComboboxInput
5+
class="example-combobox-input"
6+
placeholder="Search..."
7+
[(value)]="searchString"
8+
/>
9+
<span class="material-symbols-outlined example-icon example-arrow-icon">arrow_drop_down</span>
10+
</div>
11+
12+
<div popover="manual" #popover class="example-popover">
13+
<ng-template ngComboboxPopupContainer>
14+
<div ngListbox [multi]="true" class="example-listbox">
15+
@for (option of options(); track option) {
16+
<div class="example-option" ngOption [value]="option" [label]="option">
17+
<span>{{option}}</span>
18+
<span
19+
aria-hidden="true"
20+
class="material-symbols-outlined example-icon example-selected-icon"
21+
>check</span
22+
>
23+
</div>
24+
}
25+
</div>
26+
</ng-template>
27+
</div>
28+
</div>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import {
10+
Combobox,
11+
ComboboxInput,
12+
ComboboxPopup,
13+
ComboboxPopupContainer,
14+
} from '@angular/aria/combobox';
15+
import {Listbox, Option} from '@angular/aria/listbox';
16+
import {
17+
afterRenderEffect,
18+
ChangeDetectionStrategy,
19+
Component,
20+
ElementRef,
21+
signal,
22+
viewChild,
23+
} from '@angular/core';
24+
import {FormsModule} from '@angular/forms';
25+
26+
/** @title Readonly multiselectable combobox. */
27+
@Component({
28+
selector: 'combobox-readonly-multiselect-example',
29+
templateUrl: 'combobox-readonly-multiselect-example.html',
30+
styleUrl: '../combobox-examples.css',
31+
imports: [
32+
Combobox,
33+
ComboboxInput,
34+
ComboboxPopup,
35+
ComboboxPopupContainer,
36+
Listbox,
37+
Option,
38+
FormsModule,
39+
],
40+
changeDetection: ChangeDetectionStrategy.OnPush,
41+
})
42+
export class ComboboxReadonlyMultiselectExample {
43+
popover = viewChild<ElementRef>('popover');
44+
listbox = viewChild<Listbox<any>>(Listbox);
45+
combobox = viewChild<Combobox<any>>(Combobox);
46+
47+
options = () => states;
48+
searchString = signal('');
49+
50+
constructor() {
51+
afterRenderEffect(() => {
52+
const popover = this.popover()!;
53+
const combobox = this.combobox()!;
54+
combobox._pattern.expanded() ? this.showPopover() : popover.nativeElement.hidePopover();
55+
56+
// TODO(wagnermaciel): Make this easier for developers to do.
57+
this.listbox()?._pattern.inputs.activeItem()?.element()?.scrollIntoView({block: 'nearest'});
58+
});
59+
}
60+
61+
showPopover() {
62+
const popover = this.popover()!;
63+
const combobox = this.combobox()!;
64+
65+
const comboboxRect = combobox._pattern.inputs.inputEl()?.getBoundingClientRect();
66+
const popoverEl = popover.nativeElement;
67+
68+
if (comboboxRect) {
69+
popoverEl.style.width = `${comboboxRect.width}px`;
70+
popoverEl.style.top = `${comboboxRect.bottom + 4}px`;
71+
popoverEl.style.left = `${comboboxRect.left - 1}px`;
72+
}
73+
74+
popover.nativeElement.showPopover();
75+
}
76+
}
77+
78+
const states = ['Option 1', 'Option 2', 'Option 3'];

src/components-examples/aria/combobox/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
export {ComboboxManualExample} from './combobox-manual/combobox-manual-example';
22
export {ComboboxAutoSelectExample} from './combobox-auto-select/combobox-auto-select-example';
33
export {ComboboxHighlightExample} from './combobox-highlight/combobox-highlight-example';
4+
export {ComboboxReadonlyExample} from './combobox-readonly/combobox-readonly-example';
5+
export {ComboboxReadonlyMultiselectExample} from './combobox-readonly-multiselect/combobox-readonly-multiselect-example';
6+
47
export {ComboboxTreeManualExample} from './combobox-tree-manual/combobox-tree-manual-example';
58
export {ComboboxTreeAutoSelectExample} from './combobox-tree-auto-select/combobox-tree-auto-select-example';
69
export {ComboboxTreeHighlightExample} from './combobox-tree-highlight/combobox-tree-highlight-example';
7-
export {ComboboxReadonlyExample} from './combobox-readonly/combobox-readonly-example';
Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
1-
.example-combobox-grid {
2-
display: grid;
3-
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
4-
gap: 20px;
5-
justify-items: center;
1+
.example-combobox-row {
2+
display: flex;
3+
gap: 20px;
64
}
75

86
.example-combobox-container {
9-
display: flex;
10-
flex-direction: column;
11-
justify-content: flex-start;
12-
13-
/* stylelint-disable material/no-prefixes */
14-
width: fit-content;
15-
}
16-
17-
.example-configurable-combobox-container {
18-
padding-top: 40px;
7+
display: flex;
8+
flex-direction: column;
9+
justify-content: flex-start;
10+
min-width: 350px;
11+
padding: 20px 0;
1912
}
2013

2114
h2 {
22-
font-size: 1.1rem;
15+
font-size: 1.5rem;
16+
padding-top: 20px;
2317
}
2418

19+
h3 {
20+
font-size: 1rem;
21+
}
Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,53 @@
11
<div>
2-
<div class="example-combobox-grid">
2+
<h2>Listbox autocomplete examples</h2>
3+
4+
<div class="example-combobox-row">
35
<div class="example-combobox-container">
4-
<h2>Combobox with manual filtering</h2>
6+
<h3>Combobox with manual filtering</h3>
57
<combobox-manual-example></combobox-manual-example>
68
</div>
79

810
<div class="example-combobox-container">
9-
<h2>Combobox with auto-select filtering</h2>
11+
<h3>Combobox with auto-select filtering</h3>
1012
<combobox-auto-select-example></combobox-auto-select-example>
1113
</div>
1214

1315
<div class="example-combobox-container">
14-
<h2>Combobox with highlight filtering</h2>
16+
<h3>Combobox with highlight filtering</h3>
1517
<combobox-highlight-example></combobox-highlight-example>
1618
</div>
19+
</div>
1720

21+
<h2>Tree autocomplete examples</h2>
22+
23+
<div class="example-combobox-row">
1824
<div class="example-combobox-container">
19-
<h2>Combobox with tree popup and manual filtering</h2>
25+
<h3>Combobox with tree popup and manual filtering</h3>
2026
<combobox-tree-manual-example></combobox-tree-manual-example>
2127
</div>
2228

2329
<div class="example-combobox-container">
24-
<h2>Combobox with tree popup and auto-select filtering</h2>
30+
<h3>Combobox with tree popup and auto-select filtering</h3>
2531
<combobox-tree-auto-select-example></combobox-tree-auto-select-example>
2632
</div>
2733

2834
<div class="example-combobox-container">
29-
<h2>Combobox with tree popup and highlight filtering</h2>
35+
<h3>Combobox with tree popup and highlight filtering</h3>
3036
<combobox-tree-highlight-example></combobox-tree-highlight-example>
3137
</div>
38+
</div>
3239

40+
<h2>Select examples</h2>
41+
42+
<div class="example-combobox-row">
3343
<div class="example-combobox-container">
34-
<h2>Readonly Combobox</h2>
44+
<h3>Readonly Combobox</h3>
3545
<combobox-readonly-example></combobox-readonly-example>
3646
</div>
47+
48+
<div class="example-combobox-container">
49+
<h3>Readonly Multiselect Combobox</h3>
50+
<combobox-readonly-multiselect-example></combobox-readonly-multiselect-example>
51+
</div>
3752
</div>
3853
</div>

src/dev-app/aria-combobox/combobox-demo.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import {
1010
ComboboxAutoSelectExample,
1111
ComboboxHighlightExample,
1212
ComboboxManualExample,
13+
ComboboxReadonlyExample,
14+
ComboboxReadonlyMultiselectExample,
1315
ComboboxTreeAutoSelectExample,
1416
ComboboxTreeHighlightExample,
1517
ComboboxTreeManualExample,
16-
ComboboxReadonlyExample,
1718
} from '@angular/components-examples/aria/combobox';
1819
import {ChangeDetectionStrategy, Component} from '@angular/core';
1920

@@ -24,10 +25,11 @@ import {ChangeDetectionStrategy, Component} from '@angular/core';
2425
ComboboxManualExample,
2526
ComboboxAutoSelectExample,
2627
ComboboxHighlightExample,
28+
ComboboxReadonlyExample,
29+
ComboboxReadonlyMultiselectExample,
2730
ComboboxTreeManualExample,
2831
ComboboxTreeAutoSelectExample,
2932
ComboboxTreeHighlightExample,
30-
ComboboxReadonlyExample,
3133
],
3234
changeDetection: ChangeDetectionStrategy.OnPush,
3335
})

src/dev-app/common-classes.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
[aria-disabled='true'] .example-selectable:focus-within,
6969
[aria-activedescendant] .example-selectable:focus-within {
7070
outline-color: transparent;
71-
border-radius: 0;
7271
}
7372

7473
[aria-disabled='true'] .example-selectable[aria-selected='true'],

0 commit comments

Comments
 (0)