A month, multi-month or year calendar with something on each day: event dots, holidays, absences, availability. Single, multiple or range selection with YYYY-MM-DD values; week start, weekend and week numbers from the locale; Turkish public holidays built in. CalendarGrid is the shared grid behind every date picker.
November 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
- Article
- Newsletter
- Campaign
3 scheduled
- Black Friday launch
- Landing page refresh
- Newsletter #49
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { Calendar } from "@vamos-ui/react";
<Calendar
value={day}
onValueChange={setDay}
markers={{ "2026-11-24": [{ label: "Black Friday launch", tone: "warning" }] }}
/>Day cells expose data-today, data-selected, data-range-start / -middle / -end, data-disabled, data-outside, data-weekend and data-holiday for styling.
Cells never blur; the range band is an opaque accent mix so it stays legible on glass.
Examples
Booking: day, then time
A spa booking page: closed Mondays, a 5-week window, “slots left” dots, and CalendarSlots — a radiogroup with loading and empty states.
November 2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
- Plenty of times
- Filling up
Saturday, November 14
7 slots leftClosed on Mondays. Free cancellation up to 24 hours before.
Time off with team absences
mode="range" over two months; each day's markers are read out with the date (“Wednesday, December 23rd, 2026, Daniel Park — annual leave, …”).
December 2026 – January 2027
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
- Annual leave
- Sick leave
- Parental leave
Requesting 4 days · 2 teammates are already out on Dec 23–24.
Large cells
size="lg" gives each day a content area: marker labels, holidays, “+2 more”. Weekends get the inset surface.
November 2026
Northwind Logistics · 10 activities| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Holidays by locale
The tr locale loads Turkish public holidays (Diyanet-verified religious dates) and starts weeks on Monday. Half-day eves say “from 13:00”. Pass holidays={provider} for your own data or false to hide them.
Ekim 2026
| Pt | Sa | Ça | Pe | Cu | Ct | Pz |
|---|---|---|---|---|---|---|
| 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 |
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
- Holiday
Year view
months={12} lays out compact months in a responsive grid; prev / next move a whole year. Dots show density.
2026
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
| 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 |
- 30–47 tickets
- 48–59
- 60+
Week numbers & week start
Week start and first-week rule come from getWeekInfo (Intl.Locale with a CLDR fallback).
en-US · weeks start Sunday
November 2026
| Wk | Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|---|
| 45 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 46 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 47 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 48 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 49 | 29 | 30 | 1 | 2 | 3 | 4 | 5 |
| 50 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
en-GB · ISO weeks, Monday start
November 2026
| Wk | Mo | Tu | We | Th | Fr | Sa | Su |
|---|---|---|---|---|---|---|---|
| 44 | 26 | 27 | 28 | 29 | 30 | 31 | 1 |
| 45 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 46 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 47 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 48 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 49 | 30 | 1 | 2 | 3 | 4 | 5 | 6 |
API
Calendar
| Prop | Type | Default |
|---|---|---|
mode"none" is display only. | "single" | "multiple" | "range" | "none" | "single" |
value / defaultValueYYYY-MM-DD values, by mode. | string | null · string[] · IsoDateRange | null | — |
onValueChangeSame shape as value. | (value) => void | — |
months12 is the year view (compact cells). | 1 | 2 | 3 | 12 | 1 |
month / defaultMonth / onMonthChangeVisible month as YYYY-MM (or any date in it). onMonthChange gets YYYY-MM-01. | string | — |
onVisibleRangeChangeThe visible window, to fetch events for it. | ({ start, end }) => void | — |
markersPer-day { label, tone?, count? }. Dots in sm / md, labelled lines in lg; always part of the day's accessible name. | Record<string, CalendarMarker | CalendarMarker[]> | — |
renderDayCustom content under the number (replaces dots). | (date: Date, info: CalendarDayInfo) => ReactNode | — |
holidaysDefault: the locale pack (tr → Turkish public holidays). | HolidayProvider | HolidayProvider[] | false | — |
holidayRegionISO 3166-2 filter for regional holidays. | string | — |
min / max / disabledDaysSelectable window and unavailable days. min / max also stop navigation. | string / DayMatcher[] | — |
requiredSingle mode: the selected day can't be cleared by clicking it again. | boolean | false |
showWeekNumbersWeek number column (locale rules). | boolean | false |
weekStartsOnOverride the locale's first day (0 = Sunday). | 0–6 | — |
size32px, --control-h, or 76px cells with content. | "sm" | "md" | "lg" | "md" ("sm" in year view) |
variantcard wraps it in a surface. | "plain" | "card" | "plain" |
header / headerActionTitle, Today, prev / next; extra content in the header. | boolean / ReactNode | true |
legendKey under the grid; holidays in view are added automatically. | CalendarLegendItem[] | boolean | — |
loadingPlaceholder dots and aria-busy while the range loads. | boolean | false |
footerContent under the grid. | ReactNode | — |
gridPropsExtra react-day-picker props. | Partial<CalendarGridProps> | — |
labelscalendar namespace strings. | Partial<CalendarLabels> | — |
CalendarSlots
| Prop | Type | Default |
|---|---|---|
slots{ start: "HH:mm", end?, available, label? }. | CalendarSlot[] | — |
value / defaultValue / onValueChangeSelected start time. | string | null | — |
dayHeading (“Thursday, November 12”). | string | null | — |
loading / error / onRetrySkeleton, error with retry, and the empty state “No times available on this day”. | boolean / ReactNode / () => void | — |
hourCycle / columnsDisplay. | 12 | 24 / 2 | 3 | 4 | locale / 3 |
CalendarGrid
| Prop | Type | Default |
|---|---|---|
…DayPickerPropsmode, selected, onSelect, month, numberOfMonths, captionLayout, showWeekNumber, modifiers, disabled… pass through (Date objects). | react-day-picker v9 | — |
sizeCell size. | "sm" | "md" | "lg" | "md" |
renderDayExtraSlot under the number. | (date, modifiers) => ReactNode | — |
describeDay / dayTitleAccessible-name suffix and native tooltip. | (date, modifiers) => string | undefined | — |
markWeekendsdata-weekend from the locale's weekend. | boolean | true |