}>
  The calendar follows the [WAI-ARIA Grid Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) for date pickers. Prop getters apply all ARIA attributes automatically.

## ARIA roles and attributes

| Element | Role / Attribute | Value |
| :--- | :--- | :--- |
| Grid container | `role="grid"` | - |
| Grid container | `aria-roledescription` | `"calendar"` |
| Day cell | `role="gridcell"` | - |
| Day cell | `aria-label` | Full date (e.g. "Saturday, March 14, 2026") |
| Day cell | `aria-selected` | `true` when selected |
| Day cell | `aria-disabled` | `true` when disabled |
| Day cell | `aria-current` | `"date"` for today |
| Nav wrapper | `role="navigation"` | Set by the `CalendarNav` primitives compound component, not by the hook |
| Nav button | `aria-label` | `"Go to previous month"` / `"Go to next month"` (from `getNavProps`) |
| Nav button | `disabled` | `true` when navigation in that direction is not allowed (from `getNavProps`) |
| Month header | `aria-live` | `"polite"` |

***

## Keyboard navigation

| Key | Action |
| :--- | :--- |
| <Kbd>ArrowLeft</Kbd> / <Kbd>ArrowRight</Kbd> | Move focus +/- 1 day |
| <Kbd>ArrowUp</Kbd> / <Kbd>ArrowDown</Kbd> | Move focus +/- 1 week |
| <Kbd>PageUp</Kbd> / <Kbd>PageDown</Kbd> | Move focus +/- 1 month |
| <Kbd>Shift+PageUp</Kbd> / <Kbd>Shift+PageDown</Kbd> | Move focus +/- 1 year |
| <Kbd>Home</Kbd> / <Kbd>End</Kbd> | Move to start/end of week |
| <Kbd>Enter</Kbd> / <Kbd>Space</Kbd> | Select focused date |
| <Kbd>Escape</Kbd> | Dismiss (calls `onDismiss`) |

Focus auto-advances the displayed month when crossing boundaries. For example, pressing <Kbd>ArrowRight</Kbd> on the last day of the month moves focus to the first day of the next month and updates the displayed month.

***

## Roving tabIndex

Only the currently focused date has `tabIndex=0`. All other days have `tabIndex=-1`. This means:

* <Kbd>Tab</Kbd> moves focus into the calendar grid (to the focused date), then out
* Arrow keys move focus between days within the grid
* The user never has to tab through every day cell

***

## Screen reader announcements

The `useAnnouncer` hook (used internally by `useCalendar`) creates an `aria-live="polite"` region that announces:

* Month navigation changes (e.g. "March 2026")
* Selection changes (e.g. "Selected Saturday, March 14, 2026")

When using compound components, the announcer portal is rendered automatically inside `Calendar.Root`.

}>
  The prop getters (`getDayProps`, `getGridProps`, `getNavProps`, `getHeaderProps`) apply ARIA attributes for their respective elements automatically. Note that `getNavProps` provides `aria-label`, `disabled`, and `onClick` for individual prev/next buttons. The `role="navigation"` wrapper is provided by the `CalendarNav` primitives compound component.