Skip to content

Commit 39f2075

Browse files
committed
docs(aria/grid): calendar example with arrow key scrolling
1 parent b743840 commit 39f2075

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

src/components-examples/aria/grid/grid-calendar/grid-calendar-example.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
[enableSelection]="true"
1919
[softDisabled]="false"
2020
selectionMode="explicit"
21+
(keydown)="onKeyDown($event)"
2122
>
2223
<thead>
2324
<tr>
@@ -44,6 +45,7 @@
4445
ngGridCellWidget
4546
class="example-calendar-day-button"
4647
[attr.aria-label]="day.ariaLabel"
48+
[attr.data-day]="day.dayNum"
4749
>
4850
{{day.displayName}}
4951
</button>

src/components-examples/aria/grid/grid-calendar/grid-calendar-example.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
computed,
1515
untracked,
1616
afterRenderEffect,
17+
viewChildren,
1718
} from '@angular/core';
1819
import {DateAdapter, MAT_DATE_FORMATS, MatDateFormats} from '@angular/material/core';
1920
import {Grid, GridRow, GridCell, GridCellWidget} from '@angular/aria/grid';
@@ -25,6 +26,7 @@ interface CalendarCell<D = any> {
2526
ariaLabel: string;
2627
date: D;
2728
selected: WritableSignal<boolean>;
29+
dayNum: number;
2830
}
2931

3032
/** @title Grid Calendar. */
@@ -35,6 +37,8 @@ interface CalendarCell<D = any> {
3537
imports: [Grid, GridRow, GridCell, GridCellWidget],
3638
})
3739
export class GridCalendarExample<D> {
40+
private readonly _dayButtons = viewChildren(GridCellWidget);
41+
3842
private readonly _dateAdapter = inject<DateAdapter<D>>(DateAdapter, {optional: true})!;
3943
private readonly _dateFormats = inject<MatDateFormats>(MAT_DATE_FORMATS, {optional: true})!;
4044
private readonly _firstWeekOffset: Signal<number> = computed(() => {
@@ -62,6 +66,9 @@ export class GridCalendarExample<D> {
6266
.format(this.viewMonth(), this._dateFormats.display.monthYearLabel)
6367
.toLocaleUpperCase(),
6468
);
69+
readonly viewMonthNumDays: Signal<number> = computed(() =>
70+
this._dateAdapter.getNumDaysInMonth(this.viewMonth()),
71+
);
6572
readonly prevMonthNumDays: Signal<number> = computed(() =>
6673
this._dateAdapter.getNumDaysInMonth(this._dateAdapter.addCalendarMonths(this.viewMonth(), -1)),
6774
);
@@ -88,9 +95,6 @@ export class GridCalendarExample<D> {
8895
this._createWeekCells(this.viewMonth()),
8996
);
9097

91-
readonly scrolledUp = signal(false);
92-
readonly scrolledDown = signal(false);
93-
9498
constructor() {
9599
afterRenderEffect(() => {
96100
for (const day of this.weeks().flat()) {
@@ -110,8 +114,40 @@ export class GridCalendarExample<D> {
110114
this.viewMonth.set(this._dateAdapter.addCalendarMonths(this.viewMonth(), -1));
111115
}
112116

117+
scrollDown(): void {
118+
this.nextMonth();
119+
setTimeout(() => this._dayButtons()[0]?.element.focus());
120+
}
121+
122+
scrollUp(): void {
123+
this.prevMonth();
124+
setTimeout(() => this._dayButtons()[this._dayButtons().length - 1]?.element.focus());
125+
}
126+
127+
onKeyDown(event: KeyboardEvent): void {
128+
const day = Number((event.target as Element).getAttribute('data-day'));
129+
if (!day) return;
130+
if (day > 7 && day <= this.viewMonthNumDays() - 7) return;
131+
132+
const arrowLeft = event.key === 'ArrowLeft';
133+
const arrowRight = event.key === 'ArrowRight';
134+
const arrowUp = event.key === 'ArrowUp';
135+
const arrowDown = event.key === 'ArrowDown';
136+
137+
if ((day === 1 && arrowLeft) || (day <= 7 && arrowUp)) {
138+
this.scrollUp();
139+
}
140+
141+
if (
142+
(day === this.viewMonthNumDays() && arrowRight) ||
143+
(day > this.viewMonthNumDays() - 7 && arrowDown)
144+
) {
145+
this.scrollDown();
146+
}
147+
}
148+
113149
private _createWeekCells(viewMonth: D): CalendarCell[][] {
114-
const daysInMonth = this._dateAdapter.getNumDaysInMonth(viewMonth);
150+
const daysInMonth = this.viewMonthNumDays();
115151
const dateNames = this._dateAdapter.getDateNames();
116152
const weeks: CalendarCell[][] = [[]];
117153
for (let i = 0, cell = this._firstWeekOffset(); i < daysInMonth; i++, cell++) {
@@ -136,6 +172,7 @@ export class GridCalendarExample<D> {
136172
untracked(() => this._activeDate()),
137173
) === 0,
138174
),
175+
dayNum: i + 1,
139176
});
140177
}
141178
return weeks;

0 commit comments

Comments
 (0)