Calendar Month
- Stable
- WCAG 2.2 evidence
- RTL
A month calendar for picking a date or a date range: header with previous / next buttons and
the localised month name, weekday row, and six weeks of CalendarDays. Built on React Aria Calendar /
RangeCalendar and @internationalized/date: - Keyboard (WCAG 2.1.1): Tab reaches the buttons and the focused day; arrows move by day and week, Page Up / Page Down by month (with Shift by year), Home / End to the first and last day of the month, Enter or Space selects. RTL reverses the horizontal arrows, and the chevrons mirror.
- Locale: month names, weekday names, first day of the week, digits and calendar system follow the provider locale.
- Names and announcements (1.3.1, 4.1.2, 4.1.3): the grid is named by the visible month; each day by its full date; React Aria's live region announces the new month while paging and the selected date or range.
- minValue / maxValue and isDisabled disable dates (not focusable); isDateUnavailable keeps dates focusable but not selectable (struck through). Figma has no date picker: compose CalendarMonth inside a Popover or Dialog with a date field for one. The Figma
Month text is derived from the visible month (focusedValue / defaultFocusedValue control it). Consumer duties: time zone handling (today(getLocalTimeZone())), explaining why dates are unavailable, and a visible
label for the field the calendar fills.
import { CalendarMonth } from "@nexera-ui/react";- 8
- examples
- 27
- props
- 5
- live controls
- 1
- platform
- 8
- WCAG criteria
- 4
- blocks use it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { CalendarMonth } from "@nexera-ui/react";
<CalendarMonth />Examples 7
The same examples as Storybook, rendered live. Open Code to copy one.
Range
selectionMode="range": Enter (or a click) sets the start, a second one the end; the ends and middle use the Figma range states.
import { CalendarDate, type DateValue } from "@internationalized/date";
import { useState } from "react";
import { type RangeValue } from "react-aria-components";
import { CalendarMonth } from "@nexera-ui/react";
const october = (day: number) => new CalendarDate(2026, 10, day);
export function Range() {
const [range, setRange] = useState<RangeValue<DateValue> | null>({
start: october(12),
end: october(16),
});
return (
<div className="flex flex-col gap-2">
<CalendarMonth
selectionMode="range"
aria-label="Leave dates"
value={range}
onChange={setRange}
/>
<p className="m-0 text-body-small text-secondary">
{range ? `${range.start.toString()} to ${range.end.toString()}` : "No dates"}
</p>
</div>
);
}
Limits and unavailable dates
minValue / maxValue disable dates (not focusable); isDateUnavailable keeps weekends focusable but not selectable (struck through). A range across unavailable dates is invalid and shows errorMessage.
import { CalendarDate, isWeekend } from "@internationalized/date";
import { CalendarMonth } from "@nexera-ui/react";
const october = (day: number) => new CalendarDate(2026, 10, day);
export function LimitsAndUnavailableDates() {
return (
<CalendarMonth
selectionMode="range"
aria-label="Working days"
defaultFocusedValue={october(14)}
minValue={october(5)}
maxValue={october(28)}
isDateUnavailable={(date) => isWeekend(date, "en-US")}
errorMessage="Choose working days only."
/>
);
}
Disabled
isDisabled: every date and both buttons are disabled.
import { CalendarDate } from "@internationalized/date";
import { CalendarMonth } from "@nexera-ui/react";
const october = (day: number) => new CalendarDate(2026, 10, day);
<CalendarMonth aria-label="Leave start" defaultValue={october(14)} isDisabled />;
German
German: month and weekday names, Monday first.
import { CalendarDate } from "@internationalized/date";
import { I18nProvider } from "react-aria-components";
import { CalendarMonth } from "@nexera-ui/react";
const october = (day: number) => new CalendarDate(2026, 10, day);
export function German() {
return (
<I18nProvider locale="de-DE">
<CalendarMonth defaultValue={october(14)} aria-label="Urlaubsbeginn" />
</I18nProvider>
);
}
Right to left
Right-to-left (Arabic): Saturday first, Arabic digits, mirrored chevrons, and the arrow keys follow the reading direction.
import { CalendarDate } from "@internationalized/date";
import { CalendarMonth } from "@nexera-ui/react";
const october = (day: number) => new CalendarDate(2026, 10, day);
<CalendarMonth aria-label="بداية الإجازة" defaultValue={october(14)} />;
Narrow container
In a narrow container the columns shrink (never below the 24 px target) instead of overflowing.
import { CalendarDate } from "@internationalized/date";
import { CalendarMonth } from "@nexera-ui/react";
const october = (day: number) => new CalendarDate(2026, 10, day);
export function NarrowContainer() {
return (
<div className="max-w-[16rem] border border-dashed border-default">
<CalendarMonth aria-label="Leave start" defaultValue={october(14)} />
</div>
);
}
Custom grid
The RAC RangeCalendar composition this component wraps, for custom layouts (two months side by side, events).
import { CalendarDate } from "@internationalized/date";
import { CalendarGrid, RangeCalendar } from "react-aria-components";
import { CalendarDay } from "@nexera-ui/react";
const october = (day: number) => new CalendarDate(2026, 10, day);
export function CustomGrid() {
return (
<RangeCalendar aria-label="Trip" defaultValue={{ start: october(12), end: october(16) }}>
<CalendarGrid className={calendarMonthGridStyles()}>
{(date) => <CalendarDay date={date} />}
</CalendarGrid>
</RangeCalendar>
);
}
Props 27
Press "Try it" on a card to load that prop into the playground.
27 props shown
selectionModeNexera"single" | "range"What the user selects: one date (single, React Aria Calendar) or a start and end date. Not a Figma property.
Selects a start and an end date (React Aria RangeCalendar).
errorMessageNexeraReactNodeError text under the grid, shown with an icon while the calendar is invalid (isInvalid, or a range that contains
unavailable dates). Linked to the grid by React Aria. Say what is wrong and how to fix it.
classNameNexerastringExtra classes for the root, merged last so they win over the defaults.
styleNexeraCSSPropertiesInline style for the root.
isDateUnavailableReact Aria((date: DateValue) => boolean) | ((date: DateValue, anchorDate: CalendarDate | null) => boolean)Callback that is called for each date of the calendar. If it returns true, then the date is unavailable. Callback that is called for each date of the calendar. If it returns true, then the date is unavailable. The second argument provides the current selection anchor date, if any. This can be used to adjust the available dates based on the user's first selected date.
minValueReact AriaDateValue | nullThe minimum allowed date that a user may select.
maxValueReact AriaDateValue | nullThe maximum allowed date that a user may select.
isDisabledReact AriabooleanWhether the calendar is disabled.
isReadOnlyReact AriabooleanWhether the calendar value is immutable.
autoFocusReact AriabooleanWhether to automatically focus the calendar when it mounts.
focusedValueReact AriaDateValue | nullControls the currently focused date within the calendar.
defaultFocusedValueReact AriaDateValue | nullThe date that is focused when the calendar first mounts (uncontrolled).
isInvalidReact AriabooleanWhether the current selection is invalid according to application logic.
pageBehaviorReact Aria"single" | "visible"Controls the behavior of paging. Pagination either works by advancing the visible page by visibleDuration (default) or one unit of visibleDuration.
firstDayOfWeekReact Aria"sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat"The day that starts the week.
selectionAlignmentReact Aria"start" | "center" | "end"Determines the alignment of the visible months on initial render based on the current selection or current date if there is no selection.
weeksInMonthReact ArianumberThe number of weeks in a month. This overrides the default set by the locale.
valueReact AriaDateValue | RangeValue<DateValue> | nullThe current value (controlled).
defaultValueReact AriaDateValue | RangeValue<DateValue> | nullThe default value (uncontrolled).
onChangeReact Aria((value: DateValue) => void) | ((value: RangeValue<DateValue>) => void)Handler that is called when the value changes.
idReact AriastringThe element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).
aria-labelReact AriastringDefines a string value that labels the current element.
aria-labelledbyReact AriastringIdentifies the element (or elements) that labels the current element.
aria-describedbyReact AriastringIdentifies the element (or elements) that describes the object.
createCalendarReact Aria((identifier: CalendarIdentifier) => Calendar) | ((identifier: CalendarIdentifier) => Calendar)A function to create a new
[Calendar](https://react-spectrum.adobe.com/internationalized/date/Calendar.html) object for a
given calendar identifier. If not provided, the createCalendar function from
@internationalized/date will be used.
commitBehaviorReact Aria"clear" | "reset" | "select"Controls the behavior when a pointer is released outside the calendar or a blur occurs mid
selection: - clear: clear the currently selected range of dates.
- reset: reset the selection to the previously selected range of dates.
- select: select the currently hovered range of dates.
allowsNonContiguousRangesReact AriabooleanWhen combined with isDateUnavailable, determines whether non-contiguous ranges,
i.e. ranges containing unavailable dates, may be selected.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
6 direct · 2 supporting- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.3.2Meaningful SequenceLevel A · supporting test
- 1.4.1Use of ColorLevel A · tested directly
- 2.1.1KeyboardLevel A · tested directly
- 2.5.8Target Size (Minimum)Level AA · supporting test
- 3.3.1Error IdentificationLevel A · tested directly
- 4.1.2Name, Role, ValueLevel A · tested directly
- 4.1.3Status MessagesLevel AA · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
<CalendarMonth className="shadow-sm" />Used in blocks
- Date range pickerForms and data entry
- Week calendarScheduling and calendar
- Book a meetingScheduling and calendar
- Leave requestScheduling and calendar
Related components
- CalendarDayOne day of a {@link CalendarMonth } grid, built on React Aria `CalendarCell`: a `gridcell` whose button is named by the full, localised date ("Wednesday, October 14, 2026"), with `aria-selected`, `aria-disabled` and the "today" and range descriptions read by screen readers (WCAG 1.3.1, 4.1.2).
- CheckboxThe bare 18 px checkbox: one independent yes/no choice applied on submit, or a row selector in a table, list or tree.
- CheckboxCardA large checkbox option with an icon, a title and a description, for a few options that need explanation (notification channels, benefits).
- CheckboxFieldA checkbox with a label and optional helper text: the box (the same element as `Checkbox`) followed by the label and description, applied on submit.
- ColorInputA hex colour field with a swatch and a picker popover.
- ColorPickerPicks a colour.
- ColorTokenCardDocumentation card for one colour token: a 96 px colour sample with an "Aa" text sample, then the name, token path, hex value and contrast note as text.
- ComboboxA text field with a filtered list of options.