Overview
Accessibility
Keyboard interactions, ARIA semantics, and localization built into Colander.
Colander implements the ARIA grid pattern for calendars, so the markup you compose is accessible before you write a line of ARIA yourself. This page describes what the library does for you — and the few things left in your hands.
Keyboard interactions
Focus the grid, then:
| Key | Action |
|---|---|
ArrowRight / ArrowLeft | Move focus one day forward / back |
ArrowDown / ArrowUp | Move focus one week forward / back |
Home / End | Move focus to the first / last day of the week (respects weekStartDay) |
PageDown / PageUp | Move focus one month forward / back |
Shift + PageDown / Shift + PageUp | Move focus one year forward / back |
Enter / Space | Select the focused day |
Movement is clamped to your min/max bounds — focus stops at the boundary instead of escaping the selectable window. When focus crosses a month boundary, the view follows automatically (MonthView pages; WeeksView scrolls its window).
In a readOnly calendar, navigation still works but Enter/Space do nothing. In a disabled calendar, keyboard interaction is off entirely.
Focus management
The grid uses a roving tab index: exactly one day cell is in the tab order at a time, so the calendar occupies a single tab stop in the page. The tab target is the selected day when there is one, otherwise today, otherwise the nearest sensible day in view.
Pass autoFocus to Grid to move DOM focus into the grid when it mounts — useful when the calendar opens inside a popover:
<Grid autoFocus>{/* … */}</Grid>
Semantics and labelling
Gridrenders a<table role="grid">;DayCellTemplaterenders<td role="gridcell">cells witharia-selectedandaria-disabledreflecting state.- Each
DayButtongets a full-datearia-label(e.g. "Saturday, June 20, 2026"), localized with yourlocale. GridHeaderCellrenders abbreviated weekday text with the full weekday name as itsaria-label.- When you render a
MonthYearString, the grid is automatically linked to it witharia-labelledby, giving screen-reader users the "June 2026" context. Without one, the grid falls back toaria-label="Calendar". MonthYearString,DateString, andTimeStringrender witharia-live="polite", so month navigation and selection changes are announced without stealing focus.PrevMonthButton/NextMonthButton(and the WeeksView equivalents) carry descriptivearia-labels and use the nativedisabledattribute at bounds, so assistive tech sees real button semantics.
Outside and hidden days
outsideDays="hidden" keeps the grid shape intact for assistive tech: hidden cells stay in the DOM as empty <td> elements with aria-hidden (and a data-hidden styling hook) rather than being removed, so row and column counts remain consistent.
Range drag handles
RangeStartDragHandle / RangeEndDragHandle are pointer affordances layered on top of the keyboard-accessible selection model. They expose aria-roledescription="drag handle", a label for the boundary they control, and aria-valuetext with the current date — and they are aria-hidden while inactive. Because every range operation can also be performed by clicking or with the keyboard, dragging is an enhancement, not a requirement.
Localization
locale(BCP 47 string, default"en-US") drives every formatted string: weekday headers, month/year labels, and dayaria-labels, all viaIntl.DateTimeFormat.weekStartDay(0 = Sunday … 6 = Saturday) reorders the grid and theHome/Endkeyboard behavior together, so visual and keyboard order never disagree.timeZone(IANA identifier) controls which day is "today" and how values convert. See Dates & formats.
<MonthView temporal={Temporal} locale="de-DE" weekStartDay={1}>
{/* Mo Di Mi Do Fr Sa So */}
</MonthView>
Your responsibilities
Headless means a few things remain yours:
- Visible focus. Style
:focus-visibleonDayButton(and the nav buttons) with a clearly visible ring; the library manages where focus goes, you make it seen. - Color contrast. Selected, in-range, disabled, and outside-month states are your colors — keep them WCAG-compliant, and don't rely on color alone to convey selection.
- Hit targets. Keep day buttons comfortably tappable (44×44 px is a good floor) if you target touch devices.