Skip to content

Commit

Permalink
fix(datefield): add role="button" to the dates in the datepicker (#1375)
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] authored and GitHub Enterprise committed Nov 22, 2024
1 parent 934f4d4 commit 36daeee
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 51 deletions.
21 changes: 9 additions & 12 deletions projects/ng-aquila/src/datefield/datepicker/calendar-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,19 @@
@if (rowIndex === 0) { @for (items of [].constructor(previousItems); track $index) {
<td aria-hidden="true"></td>
} } @for (item of row; track item; let colIndex = $index) {
<td
#cell
role="gridcell"
class="nx-calendar-body-cell"
[tabindex]="_isActiveCell(rowIndex, colIndex) ? 0 : -1"
[class.nx-calendar-body-disabled]="!item.enabled"
[class.nx-calendar-body-active]="_isActiveCell(rowIndex, colIndex)"
[attr.aria-label]="item.ariaLabel"
[attr.aria-disabled]="!item.enabled || null"
(click)="_cellClicked(item)"
[style.width.%]="100 / numCols"
>
<td role="gridcell" class="nx-calendar-body-cell" [style.width.%]="100 / numCols">
<div
class="nx-calendar-body-cell-content"
[attr.aria-label]="item.ariaLabel"
[attr.aria-disabled]="!item.enabled || null"
(click)="_cellClicked(item)"
[tabindex]="_isActiveCell(rowIndex, colIndex) ? 0 : -1"
[class.nx-calendar-body-disabled]="!item.enabled"
[class.nx-calendar-body-active]="_isActiveCell(rowIndex, colIndex)"
[class.nx-calendar-body-selected]="selectedValue === item.value"
[class.nx-calendar-body-today]="todayValue === item.value"
role="button"
#cell
>
{{item.displayValue}}
</div>
Expand Down
35 changes: 17 additions & 18 deletions projects/ng-aquila/src/datefield/datepicker/calendar-body.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ $item-size: nx-spacer(3m);
height: $item-size;

margin: 0 auto;
outline: none;
@include type-style(datefield-cell);
color: v(datefield-cell-color);
border-radius: 50%;
Expand Down Expand Up @@ -86,6 +87,22 @@ $item-size: nx-spacer(3m);
color: GrayText;
}
}

&.cdk-keyboard-focused {
@include focus-style;
}

&.nx-calendar-body-disabled {
color: v(datefield-cell-disabled-color);
}

.nx-calendar-body-cell-content:not(.nx-calendar-body-selected) {
background-color: v(datefield-cell-focused-background-color);

@media screen and (forced-colors: active) {
background-color: highlight;
}
}
}

.nx-calendar-body-disabled {
Expand Down Expand Up @@ -144,24 +161,6 @@ $item-size: nx-spacer(3m);
}
}

.nx-calendar-body-cell.cdk-keyboard-focused {
.nx-calendar-body-cell-content {
@include focus-style;
}

&.nx-calendar-body-disabled .nx-calendar-body-cell-content {
color: v(datefield-cell-disabled-color);
}

.nx-calendar-body-cell-content:not(.nx-calendar-body-selected) {
background-color: v(datefield-cell-focused-background-color);

@media screen and (forced-colors: active) {
background-color: highlight;
}
}
}

.nx-calendar-adjacent-cell-content {
display: flex;
align-items: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('NxCalendarBodyComponent', () => {

const refreshElementLists = () => {
rowEls = calendarBodyNativeElement.querySelectorAll('tr');
cellEls = calendarBodyNativeElement.querySelectorAll('.nx-calendar-body-cell');
cellEls = calendarBodyNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
};

beforeEach(() => {
Expand Down Expand Up @@ -86,7 +86,7 @@ describe('NxCalendarBodyComponent', () => {
const calendarBodyDebugElement = fixture.debugElement.query(By.directive(NxCalendarBodyComponent));
calendarBodyNativeElement = calendarBodyDebugElement.nativeElement;
testComponent = fixture.componentInstance;
cellEls = calendarBodyNativeElement.querySelectorAll('.nx-calendar-body-cell');
cellEls = calendarBodyNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
});

it('should only allow selection of disabled cells when allowDisabledSelection is true', () => {
Expand Down
20 changes: 19 additions & 1 deletion projects/ng-aquila/src/datefield/datepicker/calendar-body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { FocusMonitor } from '@angular/cdk/a11y';
import {
afterNextRender,
AfterRenderPhase,
AfterViewChecked,
AfterViewInit,
ChangeDetectionStrategy,
Component,
Expand Down Expand Up @@ -57,7 +58,7 @@ export class NxCalendarCell {
standalone: true,
imports: [],
})
export class NxCalendarBodyComponent implements AfterViewInit, OnDestroy {
export class NxCalendarBodyComponent implements AfterViewInit, OnDestroy, AfterViewChecked {
/** The label for the table. (e.g. "Jan 2017"). */
@Input() label!: string;

Expand Down Expand Up @@ -101,6 +102,11 @@ export class NxCalendarBodyComponent implements AfterViewInit, OnDestroy {
/** Preserves the current value of the _cells ViewChildren in case _cells changes. */
private _cellsPrevious!: QueryList<ElementRef<HTMLElement>>;

/**
* Used to focus the active cell after change detection has run.
*/
private _focusActiveCellAfterViewChecked = false;

private readonly _destroyed = new Subject<void>();

constructor(
Expand All @@ -119,6 +125,13 @@ export class NxCalendarBodyComponent implements AfterViewInit, OnDestroy {
});
}

ngAfterViewChecked() {
if (this._focusActiveCellAfterViewChecked) {
this._focusActiveCell();
this._focusActiveCellAfterViewChecked = false;
}
}

ngOnDestroy(): void {
this._destroyed.next();
this._destroyed.complete();
Expand Down Expand Up @@ -184,4 +197,9 @@ export class NxCalendarBodyComponent implements AfterViewInit, OnDestroy {
},
);
}

/** Focuses the active cell after change detection has run and the microtask queue is empty. */
_scheduleFocusActiveCellAfterViewChecked() {
this._focusActiveCellAfterViewChecked = true;
}
}
8 changes: 4 additions & 4 deletions projects/ng-aquila/src/datefield/datepicker/calendar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ describe('NxCalendarComponent', () => {
expect(calendarInstance._currentView).toBe('multi-year');
expect(calendarInstance._activeDate).toEqual(new Date(2017, JAN, 31));

const yearCells = calendarElement.querySelectorAll('.nx-calendar-body-cell');
const yearCells = calendarElement.querySelectorAll('.nx-calendar-body-cell-content');
(yearCells[0] as HTMLElement).click();
fixture.detectChanges();

expect(calendarInstance._currentView).toBe('year');
expect(calendarInstance._activeDate).toEqual(new Date(2000, JAN, 31));

const monthCells = calendarElement.querySelectorAll('.nx-calendar-body-cell');
const monthCells = calendarElement.querySelectorAll('.nx-calendar-body-cell-content');
(monthCells[monthCells.length - 1] as HTMLElement).click();
fixture.detectChanges();

Expand All @@ -161,7 +161,7 @@ describe('NxCalendarComponent', () => {
});

it('should select date in month view', () => {
const monthCells = calendarElement.querySelectorAll('.nx-calendar-body-cell');
const monthCells = calendarElement.querySelectorAll('.nx-calendar-body-cell-content');
(monthCells[monthCells.length - 1] as HTMLElement).click();
fixture.detectChanges();

Expand Down Expand Up @@ -458,7 +458,7 @@ describe('NxCalendarComponent', () => {
});

it('should disable and prevent selection of filtered dates', () => {
const cells = calendarElement.querySelectorAll('.nx-calendar-body-cell');
const cells = calendarElement.querySelectorAll('.nx-calendar-body-cell-content');
(cells[0] as HTMLElement).click();
fixture.detectChanges();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('NxMonthView', () => {
});

it('has 31 days', () => {
const cellEls = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect(cellEls).toHaveSize(31);
});

Expand All @@ -75,7 +75,7 @@ describe('NxMonthView', () => {
});

it('fires selected change event on cell clicked', () => {
const cellEls = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
(cellEls[cellEls.length - 1] as HTMLElement).click();
fixture.detectChanges();

Expand All @@ -84,7 +84,7 @@ describe('NxMonthView', () => {
});

it('should mark active date', () => {
const cellEls = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect((cellEls[4] as HTMLElement).innerText.trim()).toBe('5');
expect(cellEls[4]).toHaveClass('nx-calendar-body-active');
});
Expand Down Expand Up @@ -312,7 +312,7 @@ describe('NxMonthView', () => {
});

it('should disable filtered dates', () => {
const cells = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cells = monthViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect(cells[0]).toHaveClass('nx-calendar-body-disabled');
expect(cells[1]).not.toHaveClass('nx-calendar-body-disabled');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('NxMultiYearView', () => {
});

it('has correct number of years', () => {
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect(cellEls).toHaveSize(yearsPerPage);
});

Expand All @@ -56,7 +56,7 @@ describe('NxMultiYearView', () => {
});

it('fires selected change event on cell clicked', () => {
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
(cellEls[cellEls.length - 1] as HTMLElement).click();
fixture.detectChanges();

Expand All @@ -65,7 +65,7 @@ describe('NxMultiYearView', () => {
});

it('should emit the selected year on cell clicked', () => {
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');

(cellEls[1] as HTMLElement).click();
fixture.detectChanges();
Expand All @@ -75,7 +75,7 @@ describe('NxMultiYearView', () => {
});

it('should mark active date', () => {
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');

expect((cellEls[cellEls.length - 3] as HTMLElement).innerText.trim()).toBe('2017');
expect(cellEls[cellEls.length - 3]).toHaveClass('nx-calendar-body-active');
Expand Down Expand Up @@ -211,7 +211,7 @@ describe('NxMultiYearView', () => {
});

it('should disable years with no enabled days', () => {
const cells = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cells = multiYearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect(cells[0]).not.toHaveClass('nx-calendar-body-disabled');
expect(cells[1]).toHaveClass('nx-calendar-body-disabled');
});
Expand Down
10 changes: 5 additions & 5 deletions projects/ng-aquila/src/datefield/datepicker/year-view.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('NxYearView', () => {
});

it('has 12 months', () => {
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect(cellEls).toHaveSize(12);
});

Expand All @@ -74,7 +74,7 @@ describe('NxYearView', () => {
});

it('fires selected change event on cell clicked', () => {
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
(cellEls[cellEls.length - 1] as HTMLElement).click();
fixture.detectChanges();

Expand All @@ -83,7 +83,7 @@ describe('NxYearView', () => {
});

it('should emit the selected month on cell clicked', () => {
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');

(cellEls[cellEls.length - 1] as HTMLElement).click();
fixture.detectChanges();
Expand All @@ -94,7 +94,7 @@ describe('NxYearView', () => {
});

it('should mark active date', () => {
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cellEls = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect((cellEls[0] as HTMLElement).innerText.trim()).toBe('Jan');
expect(cellEls[0]).toHaveClass('nx-calendar-body-active');
});
Expand Down Expand Up @@ -308,7 +308,7 @@ describe('NxYearView', () => {
});

it('should disable months with no enabled days', () => {
const cells = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell');
const cells = yearViewNativeElement.querySelectorAll('.nx-calendar-body-cell-content');
expect(cells[0]).not.toHaveClass('nx-calendar-body-disabled');
expect(cells[1]).toHaveClass('nx-calendar-body-disabled');
});
Expand Down

0 comments on commit 36daeee

Please sign in to comment.