Month grid for picking a date. RangeCalendar picks a start and end. Used inside DatePicker and DateRangePicker.
October 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 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 | 31 |
import { Calendar } from "@rdloom/react";
export default function CalendarSingleExample() {
return (
<Calendar aria-label="Delivery date" />
);
}Installation
npx rdloom add calendarCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/calendar.jsonWorks, but without upgrade tracking.
Usage
import { Calendar } from "@rdloom/react";
<Calendar aria-label="Delivery date" />Range
October 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 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 | 31 |
import { RangeCalendar } from "@rdloom/react";
export default function CalendarRangeExample() {
return (
<RangeCalendar aria-label="Trip dates" />
);
}Two months
October – November 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 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 | 31 |
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
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 | 4 | 5 |
import { RangeCalendar } from "@rdloom/react";
export default function CalendarTwoMonthsExample() {
return (
<RangeCalendar aria-label="Stay" visibleMonths={2} />
);
}Min max
October 2026
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 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 | 31 |
import { getLocalTimeZone, today } from "@internationalized/date";
import { Calendar } from "@rdloom/react";
export default function CalendarMinMaxExample() {
const now = today(getLocalTimeZone());
return (
<Calendar aria-label="Appointment" minValue={now} maxValue={now.add({ days: 30 })} />
);
}With month year selectors
June 1990
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
27 | 28 | 29 | 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 |
import { parseDate } from "@internationalized/date";
import { Calendar } from "@rdloom/react";
export default function CalendarMonthYearSelectorsExample() {
return (
<div className="flex w-full justify-center">
<Calendar aria-label="Birth date" captionLayout="dropdowns" defaultFocusedValue={parseDate("1990-06-15")} />
</div>
);
}Bordered
import { Calendar } from "@rdloom/react";
export default function CalendarBorderedExample() {
return (
<div className="flex w-full justify-center">
<Calendar aria-label="Delivery date" bordered />
</div>
);
}Bordered with selectors
import { Calendar } from "@rdloom/react";
export default function CalendarBorderedWithSelectorsExample() {
return (
<div className="flex w-full justify-center">
<Calendar aria-label="Appointment date" bordered captionLayout="dropdowns" />
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
visibleMonthsHow many months to show side by side. | number | 1 |
captionLayoutlabel shows the month and year as a heading. dropdowns shows a Month and a Year select, so a far date is two choices away. | "label" | "dropdowns" | "label" |
borderedDraws the calendar inside a rounded border with padding. | boolean | false |
minValueEarliest selectable date. | DateValue | none |
maxValueLatest selectable date. | DateValue | none |
isDisabledDisables every date. | boolean | false |
Accessibility
Role application, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
- Arrow keys move by day and week
- PageUp/PageDown change month, with Shift change year
- Home/End jump to start/end of the week
- Enter or Space selects
Screen readers announce
- The month and year are announced when the calendar opens and when paging months
- Each day announces its full date (Friday, 20 March 2026), plus selected or today
- Dates outside min/max are announced as unavailable
What your code must do
- Month heading is announced when it changes
- Unavailable dates are exposed as disabled
Guidelines
Use it when
- An always-visible calendar, such as a booking sidebar
Avoid it when
- A compact form field: use DatePicker
Don't
- Hiding which dates are unavailable until they're clicked
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-action-primary--rd-color-action-on-primary--rd-color-surface-subtle--rd-color-text-default--rd-color-text-muted--rd-color-focus-ring--rd-radius-control