Skip to content

Commit 3a2ad68

Browse files
committed
refactor(aria/toolbar): Add another example for simple-combobox and toolbar
1 parent bb4f8ec commit 3a2ad68

21 files changed

Lines changed: 923 additions & 0 deletions
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
load("//tools:defaults.bzl", "ng_project")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
ng_project(
6+
name = "toolbar",
7+
srcs = glob(["**/*.ts"]),
8+
assets = glob([
9+
"**/*.html",
10+
"**/*.css",
11+
]),
12+
deps = [
13+
"//:node_modules/@angular/core",
14+
"//:node_modules/@angular/forms",
15+
"//src/aria/combobox",
16+
"//src/aria/listbox",
17+
"//src/aria/simple-combobox",
18+
"//src/aria/toolbar",
19+
"//src/cdk/a11y",
20+
"//src/material/checkbox",
21+
"//src/material/form-field",
22+
"//src/material/select",
23+
],
24+
)
25+
26+
filegroup(
27+
name = "source-files",
28+
srcs = glob([
29+
"**/*.html",
30+
"**/*.css",
31+
"**/*.ts",
32+
]),
33+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export {ToolbarBasicHorizontalExample} from './toolbar-basic-horizontal/toolbar-basic-horizontal-example';
2+
export {ToolbarBasicVerticalExample} from './toolbar-basic-vertical/toolbar-basic-vertical-example';
3+
export {ToolbarConfigurableExample} from './toolbar-configurable/toolbar-configurable-example';
4+
export {ToolbarRtlExample} from './toolbar-rtl/toolbar-rtl-example';
5+
export {ToolbarHardDisabledExample} from './toolbar-hard-disabled/toolbar-hard-disabled-example';
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import {Combobox, ComboboxPopup, ComboboxWidget} from '@angular/aria/simple-combobox';
2+
import {Listbox, Option} from '@angular/aria/listbox';
3+
import {ToolbarWidget} from '@angular/aria/toolbar';
4+
import {Dir, Directionality} from '@angular/cdk/bidi';
5+
import {
6+
afterRenderEffect,
7+
Component,
8+
Directive,
9+
ElementRef,
10+
inject,
11+
signal,
12+
viewChild,
13+
} from '@angular/core';
14+
import {OverlayModule} from '@angular/cdk/overlay';
15+
16+
@Directive({
17+
selector: 'button[toolbar-button]',
18+
standalone: true,
19+
hostDirectives: [{directive: ToolbarWidget, inputs: ['value', 'disabled']}],
20+
host: {
21+
type: 'button',
22+
class: 'example-button material-symbols-outlined',
23+
'[aria-label]': 'widget.value()',
24+
},
25+
})
26+
export class SimpleToolbarButton {
27+
widget = inject(ToolbarWidget);
28+
}
29+
30+
@Directive({
31+
selector: 'button[toolbar-toggle-button]',
32+
standalone: true,
33+
hostDirectives: [{directive: ToolbarWidget, inputs: ['value']}],
34+
host: {
35+
type: 'button',
36+
class: 'example-button material-symbols-outlined',
37+
'[aria-pressed]': 'widget.selected()',
38+
'[aria-label]': 'widget.value()',
39+
},
40+
})
41+
export class SimpleToolbarToggleButton {
42+
widget = inject(ToolbarWidget);
43+
}
44+
45+
@Directive({
46+
selector: 'button[toolbar-radio-button]',
47+
standalone: true,
48+
hostDirectives: [{directive: ToolbarWidget, inputs: ['value', 'disabled']}],
49+
host: {
50+
role: 'radio',
51+
type: 'button',
52+
class: 'example-button material-symbols-outlined',
53+
'[aria-checked]': 'widget.selected()',
54+
'[aria-label]': 'widget.value()',
55+
},
56+
})
57+
export class SimpleToolbarRadioButton {
58+
widget = inject(ToolbarWidget);
59+
}
60+
61+
@Component({
62+
selector: 'combobox',
63+
standalone: true,
64+
imports: [
65+
Dir,
66+
Combobox,
67+
ComboboxPopup,
68+
ComboboxWidget,
69+
Listbox,
70+
Option,
71+
ToolbarWidget,
72+
OverlayModule,
73+
],
74+
styleUrl: 'toolbar-common.css',
75+
host: {class: 'example-combobox-container'},
76+
template: `
77+
<div class="example-combobox" [dir]="dir()">
78+
<div #origin class="example-combobox-input-container"
79+
ngCombobox
80+
#combobox="ngCombobox"
81+
ngToolbarWidget
82+
[(value)]="value"
83+
[(expanded)]="popupExpanded"
84+
(click)="origin.focus()">
85+
<div class="example-combobox-input" style="display: flex; align-items: center;" aria-label="Select a text style">
86+
{{ value() }}
87+
</div>
88+
<span class="material-symbols-outlined example-icon example-arrow-icon"
89+
>arrow_drop_down</span
90+
>
91+
</div>
92+
93+
<ng-template [cdkConnectedOverlay]="{origin, usePopover: 'inline', matchWidth: true}" [cdkConnectedOverlayOpen]="true"
94+
[cdkConnectedOverlayDisableClose]="true">
95+
<ng-template ngComboboxPopup [combobox]="combobox">
96+
<div ngListbox ngComboboxWidget [(value)]="selectedOption" class="example-listbox example-popup" focusMode="activedescendant"
97+
[tabIndex]="-1" selectionMode="explicit" (click)="onCommit()"
98+
(keydown.enter)="onCommit()"
99+
(pointerdown)="$event.preventDefault()">
100+
@for (option of options; track option) {
101+
<div ngOption [value]="option" [label]="option" class="example-option example-selectable example-stateful">
102+
<span>{{option}}</span>
103+
<span aria-hidden="true" class="material-symbols-outlined example-option-icon"
104+
>check</span
105+
>
106+
</div>
107+
}
108+
</div>
109+
</ng-template>
110+
</ng-template>
111+
</div>
112+
`,
113+
})
114+
export class SimpleCombobox {
115+
dir = inject(Directionality).valueSignal;
116+
listbox = viewChild(Listbox);
117+
combobox = viewChild(Combobox);
118+
119+
popupExpanded = signal(false);
120+
selectedOption = signal<string[]>([]);
121+
value = signal('Normal text');
122+
options = ['Normal text', 'Title', 'Subtitle', 'Heading 1', 'Heading 2', 'Heading 3'];
123+
124+
constructor() {
125+
afterRenderEffect(() => {
126+
this.listbox()?.scrollActiveItemIntoView();
127+
});
128+
}
129+
130+
onCommit() {
131+
const selectedOption = this.selectedOption();
132+
if (selectedOption.length > 0) {
133+
this.value.set(selectedOption[0]);
134+
}
135+
this.popupExpanded.set(false);
136+
}
137+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<div class="example-toolbar-container">
2+
<div ngToolbar class="example-toolbar" aria-label="Horizontal Toolbar Text Formatting Tools">
3+
<div class="example-group" aria-label="Undo and Redo options">
4+
<button toolbar-button value="undo">undo</button>
5+
<button toolbar-button value="redo">redo</button>
6+
</div>
7+
8+
<div class="example-separator" role="separator"></div>
9+
10+
<div class="example-group" aria-label="Text formatting options">
11+
<button toolbar-toggle-button value="bold">format_bold</button>
12+
<button toolbar-toggle-button value="italic">format_italic</button>
13+
<button toolbar-toggle-button value="underline">format_underlined</button>
14+
</div>
15+
16+
<div class="example-separator" role="separator"></div>
17+
18+
<combobox />
19+
20+
<div class="example-separator" role="separator"></div>
21+
22+
<div
23+
ngToolbarWidgetGroup
24+
role="radiogroup"
25+
class="example-group"
26+
aria-label="Alignment options"
27+
>
28+
<button toolbar-radio-button value="align left">format_align_left</button>
29+
<button toolbar-radio-button value="align center">format_align_center</button>
30+
<button toolbar-radio-button value="align right">format_align_right</button>
31+
</div>
32+
33+
<div class="example-separator" role="separator"></div>
34+
35+
<div ngToolbarWidgetGroup role="radiogroup" class="example-group" aria-label="List options">
36+
<button toolbar-radio-button value="checklist">checklist</button>
37+
<button toolbar-radio-button value="bullet list">format_list_bulleted</button>
38+
<button toolbar-radio-button value="numbered list">format_list_numbered</button>
39+
</div>
40+
</div>
41+
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {Component} from '@angular/core';
2+
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';
3+
import {
4+
SimpleCombobox,
5+
SimpleToolbarButton,
6+
SimpleToolbarRadioButton,
7+
SimpleToolbarToggleButton,
8+
} from '../simple-toolbar';
9+
10+
/** @title Basic Horizontal Toolbar Example */
11+
@Component({
12+
selector: 'toolbar-basic-horizontal-example',
13+
templateUrl: 'toolbar-basic-horizontal-example.html',
14+
styleUrl: '../toolbar-common.css',
15+
imports: [
16+
Toolbar,
17+
ToolbarWidget,
18+
ToolbarWidgetGroup,
19+
SimpleCombobox,
20+
SimpleToolbarButton,
21+
SimpleToolbarRadioButton,
22+
SimpleToolbarToggleButton,
23+
],
24+
})
25+
export class ToolbarBasicHorizontalExample {}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<div class="example-toolbar-container">
2+
<div
3+
ngToolbar
4+
orientation="vertical"
5+
class="example-toolbar"
6+
aria-label="Vertical Toolbar Text Formatting Tools"
7+
>
8+
<div class="example-group" aria-label="Undo and Redo options">
9+
<button toolbar-button value="undo">undo</button>
10+
<button toolbar-button value="redo">redo</button>
11+
</div>
12+
13+
<div class="example-separator" role="separator"></div>
14+
15+
<div class="example-group" aria-label="Text formatting options">
16+
<button toolbar-toggle-button value="bold">format_bold</button>
17+
<button toolbar-toggle-button value="italic">format_italic</button>
18+
<button toolbar-toggle-button value="underline">format_underlined</button>
19+
</div>
20+
21+
<div class="example-separator" role="separator"></div>
22+
23+
<div
24+
ngToolbarWidgetGroup
25+
role="radiogroup"
26+
class="example-group"
27+
aria-label="Alignment options"
28+
>
29+
<button toolbar-radio-button value="align left">format_align_left</button>
30+
<button toolbar-radio-button value="align center">format_align_center</button>
31+
<button toolbar-radio-button value="align right">format_align_right</button>
32+
</div>
33+
</div>
34+
</div>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {Component} from '@angular/core';
2+
import {Toolbar, ToolbarWidget, ToolbarWidgetGroup} from '@angular/aria/toolbar';
3+
import {
4+
SimpleToolbarButton,
5+
SimpleToolbarRadioButton,
6+
SimpleToolbarToggleButton,
7+
} from '../simple-toolbar';
8+
9+
/** @title Basic Vertical Toolbar Example */
10+
@Component({
11+
selector: 'toolbar-basic-vertical-example',
12+
templateUrl: 'toolbar-basic-vertical-example.html',
13+
styleUrl: '../toolbar-common.css',
14+
imports: [
15+
Toolbar,
16+
ToolbarWidget,
17+
ToolbarWidgetGroup,
18+
SimpleToolbarButton,
19+
SimpleToolbarRadioButton,
20+
SimpleToolbarToggleButton,
21+
],
22+
})
23+
export class ToolbarBasicVerticalExample {}

0 commit comments

Comments
 (0)