a11y

Calendar

Month-view calendar — standalone widget for picking a single date or a date range. Built on the WrDateAdapter abstraction. Click the header label to zoom into month / year quick-pick views.

Installation

import { WrCalendar } from 'ngwr/calendar';
import { provideWrDateAdapter } from 'ngwr/date';

// In main.ts
bootstrapApplication(AppComponent, {
  providers: [provideWrDateAdapter()],
});

// In any component
@Component({ imports: [WrCalendar] })
export class MyComponent {
  protected readonly picked = signal<Date | null>(new Date());
}

Single date

Default mode. Two-way bind a Date (or null).

<wr-calendar [(date)]="picked" />
SunMonTueWedThuFriSat

Date range

Set mode="range" and bind [(range)] to a [start, end] tuple. Hovering after picking the start previews the would-be selection.

<wr-calendar mode="range" [(range)]="picked" />
SunMonTueWedThuFriSat

Bounds + filter

min / max clamp the selectable range; dateFilter is a predicate that disables individual dates (here: only weekdays).

<wr-calendar
  [(date)]="picked"
  [min]="firstOfYear"
  [max]="lastOfYear"
  [dateFilter]="isWeekday"
/>
SunMonTueWedThuFriSat

Keyboard

The grid is a SINGLE tab stop with a roving cursor — tabbing through a month is not 42 stops — so exactly one cell is tabbable at a time and the arrows move it. The header's / buttons and the month/year label are separate, ordinary tab stops before it.

Day view. Focus is on the grid; the cursor is the cell with the ring.
KeyDoes
ArrowLeftArrowRightPrevious / next day. The pair swaps under dir="rtl" — these name a side of the screen.
ArrowUpArrowDownSame weekday, one week back / forward.
HomeEnd First / last day of the current week — which respects the adapter's first day of the week, not Sunday.
PageUpPageDownPrevious / next month, scrolling the view with it.
Shift + PageUpShift + PageDownPrevious / next year.
EnterSpacePicks the day under the cursor — the same commit as a click, including the second click of a range.
Month and year quick-pick, reached by activating the header label.
KeyDoes
ArrowLeftArrowRightPrevious / next chip, mirrored under dir="rtl".
ArrowUpArrowDownOne full row: three chips in the month view, four in the year view.
HomeEnd First / last chip on the page. The list does not wrap or spill into the next twelve — the header's / are what change which twelve.
EnterSpaceLeft to the browser: each chip is a real <button>.

A cursor never parks on a day it cannot pick. With [min], [max] or [dateFilter] in play, a keystroke that lands on a disabled cell keeps travelling in the direction it was already going, and stops only when the run does. Not cosmetic: the cursor cell holds the grid's only tabindex="0", so parking it on a disabled button would leave the calendar with zero tabbable cells — you could tab out of it and never tab back in.

API

NameDescriptionTypeDefault
modeSelection mode.WrCalendarMode'single'
dateTwo-way bindable single value (used when mode === 'single').Date | nullnull
rangeTwo-way bindable [start, end] (used when mode === 'range').WrCalendarRange[null, null]
minMin selectable date (inclusive).Date | nullnull
maxMax selectable date (inclusive).Date | nullnull
dateFilterPredicate — return false to disable specific dates (e.g. weekends only).((date: Date) => boolean) | nullnull
autoFocusMove real focus onto the roving cell as soon as the grid is on screen. Off by default: a standalone <wr-calendar> sitting in a page must not steal focus on load. wr-date-picker turns it on for the popup it opens from its trigger, where the user asked to be taken to the calendar.booleanfalse
disabledDisable interaction entirely.booleanfalse

CSS variables

Custom properties ngwr/calendar publishes. Each default below is declared on the component's own selector, so a :root override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.

VariableDefaultDeclared on
--wr-calendar-accentvar(--wr-color-primary).wr-calendar
--wr-calendar-accent-contrastvar(--wr-color-primary-contrast).wr-calendar
--wr-calendar-accent-inkvar(--wr-color-primary-ink).wr-calendar
--wr-calendar-accent-rgbvar(--wr-color-primary-rgb).wr-calendar
--wr-calendar-bgvar(--wr-color-surface).wr-calendar
--wr-calendar-bordervar(--wr-color-outline).wr-calendar
--wr-calendar-cell-size2rem.wr-calendar
--wr-calendar-colorvar(--wr-color-on-surface).wr-calendar
--wr-calendar-day-radiusvar(--wr-border-radius-sm).wr-calendar
--wr-calendar-mutedvar(--wr-color-on-surface-muted).wr-calendar
--wr-calendar-radiusvar(--wr-border-radius-base).wr-calendar
--wr-calendar-width17rem.wr-calendar