Calendar
Usage
September 2026
| Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|---|---|---|---|---|---|
30 | 31 | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 1 | 2 | 3 |
Selected date: 2026-09-30
function InspectionDate() {
const [date, setDate] = useState<string | null>("2026-09-30");
return (
<Calendar
label="Inspection date"
value={date}
onValueChange={setDate}
min="2026-01-01"
max="2026-12-31"
/>
);
}
Values and inclusive bounds use YYYY-MM-DD, with years from 0001 through 9999. Null means no selection. Dates are Gregorian calendar values; they never pass through JavaScript local-time parsing. Invalid dates and reversed bounds show an error. Invalid bounds disable selection until corrected.
Disabled and read-only
Use disabled to make the calendar unavailable, or readOnly to allow inspection without changing its selection. required displays an error when the controlled value is null. The parent owns the selected value and its form validation.
Props
| PROP | TYPE | DEFAULT | REQUIRED |
|---|---|---|---|
label | string | — | yes |
valueYYYY-MM-DD in years 0001–9999, or null for no selection. Never an instant or a local Date. | string | — | yes |
onValueChangeRequests the chosen date-only string. The parent accepts it through value. | function | — | yes |
minInclusive YYYY-MM-DD lower bound. | string | — | no |
maxInclusive YYYY-MM-DD upper bound. | string | — | no |
disabled | boolean | false | no |
readOnly | boolean | false | no |
required | boolean | false | no |
id | string | — | no |
className | string | — | no |
Accessibility
- React Aria supplies the named calendar, month navigation, day arrows and Enter/Space selection.
- Dates have full accessible names. Disabled bounds cannot be selected.
- Focus uses the shared border and shadow tokens, and in forced colors a system outline marks the focused day or month button. Day targets are 32 CSS pixels where there is room and shrink to no less than 24 in a narrow container, so the calendar fits about 170 px without spilling; labels use at least 11px text.
- The forwarded ref identifies the calendar's named root. Use DatePicker when an error summary needs to focus an editable date field.
Manifest entry
<Calendar label="Inspection date" value={date} onValueChange={setDate} min="2026-01-01" max="2026-12-31" />View agent manifest
{
"description": "Controlled Gregorian calendar with date-only strings, keyboard day/month navigation, strict date bounds and visible configuration errors.",
"props": {
"label": {
"type": "string",
"required": true
},
"value": {
"type": "string",
"required": true,
"description": "YYYY-MM-DD in years 0001–9999, or null for no selection. Never an instant or a local Date."
},
"onValueChange": {
"type": "function",
"required": true,
"description": "Requests the chosen date-only string. The parent accepts it through value."
},
"min": {
"type": "string",
"description": "Inclusive YYYY-MM-DD lower bound."
},
"max": {
"type": "string",
"description": "Inclusive YYYY-MM-DD upper bound."
},
"disabled": {
"type": "boolean",
"default": false
},
"readOnly": {
"type": "boolean",
"default": false
},
"required": {
"type": "boolean",
"default": false
},
"id": {
"type": "string"
},
"className": {
"type": "string"
}
},
"composable_with": [
"FormSection",
"DatePicker"
],
"never_inside": [
"Button"
],
"example": "<Calendar label=\"Inspection date\" value={date} onValueChange={setDate} min=\"2026-01-01\" max=\"2026-12-31\" />"
}