Skip to Content
⭐️ Leave a star →
ComponentsCalendar

Calendar

Headless month calendar. Compose Nav + Title + Grid. Render each day with a render-prop and let data attributes drive selected, today, outside-month, and disabled styling.

Features

Controlled and uncontrolled selection.
Controlled and uncontrolled visible month.
minDate, maxDate, and a custom isDateDisabled predicate.
Configurable weekStartsOn and locale.
Render-prop renderDay / renderWeekday for full visual control.
data-selected, data-today, data-outside-month, data-disabled, data-weekend.

Example

June 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat

Selected: 6/30/2026

import { Calendar } from '@wire-ui/react' <Calendar.Root> <Calendar.Nav> <Calendar.PrevButton /> <Calendar.Title /> <Calendar.NextButton /> </Calendar.Nav> <Calendar.Grid renderDay={(day) => ( <button {...day.props}>{day.dayOfMonth}</button> )} renderWeekday={(wd) => <div>{wd.short}</div>} /> </Calendar.Root>

Styling

Each day cell exposes data-selected, data-today, data-outside-month, data-disabled, and data-weekend. The PrevButton and NextButton auto-disable when crossing minDate / maxDate.

<button {...day.props} className=" rounded-[6px] p-1.5 data-[selected]:bg-black data-[selected]:text-white data-[today]:font-bold data-[today]:underline data-[outside-month]:text-[#a3a3a3] data-[weekend]:text-[#6b7280] data-[disabled]:opacity-30 data-[disabled]:cursor-not-allowed "> {day.dayOfMonth} </button>

Using data attributes

The render-prop hands you a fully spreadable day.props object containing the role, button type, tabIndex, aria-selected, aria-current, the click handler, and all data-* flags.

[data-selected] { background: #000; color: #fff; } [data-today] { font-weight: 700; text-decoration: underline; } [data-outside-month] { color: #a3a3a3; } [data-disabled] { opacity: 0.3; cursor: not-allowed; }

Root props

PropTypeDefaultDescription
valueDate | nullControlled selected date
defaultValueDate | nullnullInitial selected date
onChange(date: Date | null) => voidCalled when selection changes
monthDateControlled visible month
defaultMonthDatetoday / valueInitial visible month
onMonthChange(month: Date) => voidCalled when the visible month changes
minDateDateEarliest selectable date
maxDateDateLatest selectable date
isDateDisabled(date: Date) => booleanCustom predicate to disable specific dates
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 60First day of the week (0 = Sunday)
localestring'en-US'Locale for weekday and month names

Grid props

PropTypeDescription
renderDay(day: CalendarDay) => ReactNodeRender each day cell
renderWeekday(wd: { name: string; short: string }) => ReactNodeRender each weekday header

CalendarDay shape

FieldTypeDescription
dateDateThe day’s date
dayOfMonthnumber1-31
isTodaybooleanTrue if the cell is today
isSelectedbooleanTrue if the cell equals the selected value
isOutsideMonthbooleanTrue if the cell is from the previous or next month
isDisabledbooleanTrue if min/max/predicate disables this date
isWeekendbooleanTrue for Saturday or Sunday
propsobjectSpread onto your button — includes ARIA + data-* + onClick

PrevButton / NextButton

Auto-disabled when stepping outside minDate / maxDate. Render < / > characters by default; pass children to override.

Title

Renders the localised “Month Year” string for the visible month. Pass children to fully override.

Data attributes

AttributeElementWhen present
data-selectedday buttonCell equals the selected value
data-todayday buttonCell is today
data-outside-monthday buttonCell belongs to prev/next month
data-disabledday buttonCell is disabled
data-weekendday buttonCell is Saturday or Sunday

Accessibility

  • The Root renders with role="application" and aria-label="Calendar".
  • The Grid is role="grid"; weekday cells use role="columnheader".
  • Each day cell is a real <button> with aria-selected and aria-current="date" for today.
  • The selected day gets tabIndex=0, others -1 — keep keyboard focus in a single cell.

Keyboard Interactions

KeyDescription
TabMoves focus into the grid (lands on the selected day, or the first focusable cell).
Enter / SpaceSelects the focused day.
Last updated on

MIT License © 2026 wire-ui

Calendar – Wire UI