ComponentsCalendar
Calendar
Let users choose a date or date range from a month view.
On this page
Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.
View registry filesImport the component into your page or component file.
import { Calendar, RangeCalendar } from "@dethink/components";
import { CalendarDate } from "@internationalized/date";Try the examples, then open the code to use them in your app. Move focus into a grid and navigate with the arrow keys, PageUp/PageDown for months, and Enter or Space to select.
Single date
A controlled Calendar — value and onValueChange pair with React state holding a CalendarDate.
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
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 | 1 | 2 |
Selected: 2026-07-14
Show sourceexamples/calendar/basic.tsx
"use client";
import { useState } from "react";
import { Calendar } from "@dethink/components";
import { CalendarDate, type DateValue } from "@internationalized/date";
export function CalendarBasic() {
const [value, setValue] = useState<DateValue | null>(
new CalendarDate(2026, 7, 14),
);
return (
<div className="flex flex-col items-center gap-3">
<Calendar
aria-label="Launch date"
value={value}
onValueChange={setValue}
/>
<p className="text-muted-foreground text-sm">
Selected: {value ? value.toString() : "none"}
</p>
</div>
);
}Range
RangeCalendar selects a start and end date in one grid; the value is a { start, end } pair.
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
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 | 1 | 2 |
Show sourceexamples/calendar/range.tsx
"use client";
import { RangeCalendar } from "@dethink/components";
import { CalendarDate } from "@internationalized/date";
export function CalendarRange() {
return (
<div className="flex justify-center">
<RangeCalendar
aria-label="Sprint dates"
defaultValue={{
start: new CalendarDate(2026, 7, 6),
end: new CalendarDate(2026, 7, 17),
}}
/>
</div>
);
}Bounds and unavailable dates
minValue and maxValue clamp selection to a window, while isDateUnavailable strikes out individual dates — here, weekends.
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
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 | 1 | 2 |
Locale and week start
locale drives month and weekday formatting, weekStartsOn overrides the first day of the week, and weekdayStyle switches the header format.
| Mo | Di | Mi | Do | Fr | Sa | So |
|---|---|---|---|---|---|---|
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 | 1 | 2 |
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
|---|---|---|---|---|---|---|
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 | 1 |
Show sourceexamples/calendar/locale.tsx
"use client";
import { Calendar } from "@dethink/components";
import { CalendarDate } from "@internationalized/date";
export function CalendarLocale() {
return (
<div className="flex flex-wrap items-start justify-center gap-6">
<Calendar
aria-label="Date (German)"
locale="de-DE"
weekStartsOn="mon"
defaultValue={new CalendarDate(2026, 7, 14)}
/>
<Calendar
aria-label="Date (Japanese)"
locale="ja-JP"
weekdayStyle="narrow"
defaultValue={new CalendarDate(2026, 7, 14)}
/>
</div>
);
}Calendar and RangeCalendar share the same API; RangeCalendar's value shape is { start, end }. Always give each calendar an aria-label (or aria-labelledby) describing what is being picked.
| Prop | What it does | Default |
|---|---|---|
valueDateValue | null | Controlled selected date, built with @internationalized/date (for RangeCalendar: { start, end }). | Not set |
defaultValueDateValue | null | The starting selection when the component manages its own state. | Not set |
onValueChange(value) => void | Fires with the new date (or range) whenever the selection changes. | Not set |
minValue / maxValueDateValue | Inclusive bounds; dates outside them cannot be selected. | Not set |
isDateUnavailable(date: DateValue) => boolean | Marks individual dates unavailable — rendered struck through and unselectable. | Not set |
disabledboolean | Disables the whole calendar. | false |
invalidboolean | Marks the current selection invalid for form validation. | false |
isReadOnlyboolean | Selection is visible and focusable but cannot change (react-aria passthrough). | false |
localestring | BCP 47 tag (for example "de-DE") controlling month/weekday formatting. | runtime locale |
weekStartsOn"sun" | "mon" | … | "sat" | First day of the week, overriding the locale. | locale default |
weekdayStyle"narrow" | "short" | "long" | Weekday header format. | "short" |