Skip to content
Ndop UI

Calendar primitive

Headless Calendar: the behavior, keyboard support and ARIA of the WAI-ARIA Date grid pattern, with no styles.

Import

Primitives ship in the @ndop/primitives package and have no styles. Their state is on data attributes for you to style. The styled Calendar is built on this one.

import {
  NdCalendar,
  NdCalendarMonth,
  NdCalendarWeekday,
  NdCalendarCell,
  NdCalendarDay,
  NdCalendarGrid,
  NdCalendarHeading,
  NdCalendarNext,
  NdCalendarPrevious,
} from '@ndop/primitives/calendar';

Accessibility

Implements the Date grid pattern of the WAI-ARIA Authoring Practices.

Keyboard

Keys the component handles.

Key Action
TabMoves focus to the day in the tab order, then out of the grid.
ArrowRightorArrowLeftMoves focus to the next or previous day, changing month when needed.
ArrowDownorArrowUpMoves focus to the same day of the next or previous week.
HomeorEndMoves focus to the first or last day of the week.
PageDownorPageUpMoves focus to the same day of the next or previous month.
Shift+PageDownorShift+PageUpMoves focus to the same day of the next or previous year.
EnterorSpaceChooses the focused day, unless it's disabled.

Focus

  • Focus never leaves the shown months on its own: moving past their edge shows the next or previous month and focuses the day there.
  • min and max stop the keys at their bounds.
  • Choosing a day keeps focus on it.

Right-to-left

In right-to-left layouts, the days run from right to left, so ArrowLeft moves to the next day and ArrowRight to the previous one. Direction comes from the nearest dir attribute.

API reference

NdCalendar

[ndCalendar]from @ndop/primitives/calendar

A calendar: month grids to choose a date, a range or several dates, on the WAI-ARIA date grid pattern with a roving tabindex. Its structure is the user's template, looping over NdCalendar.months and NdCalendar.weekdays; dates use Date and Intl only. It owns its value, so it's a ControlValueAccessor that Signal Forms ([formField]), reactive and template-driven forms bind (ADR-0004, amendments 1 and 4): a Date in single mode, an NdDateRange in range mode, a list of dates in multiple mode.

NdCalendar binding Type Default
[mode]
How it chooses dates.
'single' | 'range' | 'multiple''single'
[defaultMonth]
The first month shown when month isn't bound.
Date | nullnull
[numberOfMonths]
How many months show side by side.
number1
[min]
The earliest day that can be chosen.
Date | nullnull
[max]
The latest day that can be chosen.
Date | nullnull
[disabledDates]
Disables days it returns true for, such as weekends.
((date: Date) => boolean) | nullnull
[weekStartsOn]
The first weekday, 0 for Sunday; defaults to the locale's.
number | nullnull
[locale]
The locale for names and labels; defaults to the app's LOCALE_ID.
stringinject(LOCALE_ID)
[showOutsideDays]
Shows the neighboring months' days that fill the first and last weeks.
booleantrue
[(value)]
The chosen date in single mode. Two-way bindable with [(value)].
Date | nullnull
[(range)]
The chosen days in range mode. Two-way bindable with [(range)].
NdDateRange{ from: null, to: null }
[(values)]
The chosen dates in multiple mode. Two-way bindable with [(values)].
readonly Date[][]
[(month)]
The first month shown. Two-way bindable with [(month)].
Date | nullnull
Data attribute Values
data-mode —

NdCalendarMonth

[ndCalendarMonth]from @ndop/primitives/calendar

One shown month: wraps its heading and grid.

NdCalendarMonth binding Type Default
[month]required
The month, from NdCalendar.months.
NdCalendarMonthView—

NdCalendarWeekday

th[ndCalendarWeekday]from @ndop/primitives/calendar

A weekday's column header, with the full name in abbr.

Manages abbr, scope.

NdCalendarWeekday binding Type Default
[weekday]required
The weekday, from NdCalendar.weekdays.
NdCalendarWeekdayView—

NdCalendarCell

td[ndCalendarCell]role gridcellfrom @ndop/primitives/calendar

A day's cell (role="gridcell"), on a native td, with aria-selected when the day is chosen. Its data attributes repeat its day's state, for styling.

Manages aria-selected.

NdCalendarCell binding Type Default
[day]required
The day, from a week of NdCalendar.months.
NdCalendarDayView—
Data attribute Values
data-selected —
data-today —
data-outside —
data-hidden —
data-disabled —
data-range-start —
data-range-middle —
data-range-end —

NdCalendarDay

button[ndCalendarDay]from @ndop/primitives/calendar

A day's button, labelled with the full date. Only one day is in the tab order; the date grid keys move focus. Hidden outside days render nothing clickable: the button gets hidden.

Manages aria-label, aria-current, aria-disabled, tabindex.

NdCalendarDay binding Type Default
[day]required
The day, from a week of NdCalendar.months.
NdCalendarDayView—
Data attribute Values
data-day —
data-selected-single —
data-range-start —
data-range-middle —
data-range-end —
data-today —
data-outside —
data-disabled —

NdCalendarGrid

table[ndCalendarGrid]role gridfrom @ndop/primitives/calendar

Its month's grid of days (role="grid"), on a native table.

Manages aria-labelledby, aria-multiselectable.

NdCalendarHeading

[ndCalendarHeading]from @ndop/primitives/calendar

Its month's name and year: a polite live region, so changing months is announced, and the label of its grid.

Manages id, aria-live.

NdCalendarNext

button[ndCalendarNext]from @ndop/primitives/calendar

The button that shows the next month. Name it with aria-label.

Manages aria-disabled.

Data attribute Values
data-disabled —

NdCalendarPrevious

button[ndCalendarPrevious]from @ndop/primitives/calendar

The button that shows the previous month. Name it with aria-label.

Manages aria-disabled.

Data attribute Values
data-disabled —