Marble UI
← Components

Calendar

Preview: Single

Month grid for picking a date (or a range with RangeCalendar), locale-aware and keyboard navigable.

Import

import { Calendar, RangeCalendar } from '@marbleui/ui'

Props

<Calendar>

PropTypeDefaultDescription
months1 | 21Show N months side by side.

Also accepts React Aria props (100).

<RangeCalendar>

PropTypeDefaultDescription
months1 | 21

Also accepts React Aria props (101).

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Button · React Aria Calendar · React Aria CalendarCell · React Aria CalendarGrid · React Aria CalendarGridBody · React Aria CalendarGridHeader · React Aria CalendarHeaderCell · React Aria Heading · React Aria RangeCalendar. Follow the primitive's docs for the full keyboard map.

Usage notes

Month grid for choosing a date, or a range with RangeCalendar (both exported from here). For a date field with a popover use DatePicker or DateRangePicker.

<Calendar aria-label="Appointment date" minValue={today(getLocalTimeZone())} onChange={setDate} />
<RangeCalendar aria-label="Trip" months={2} />
  • Values are @internationalized/date objects (such as CalendarDate), not JS Date. Uncontrolled: defaultValue. Controlled: value + onChange. A range is { start, end }.
  • Limit selection with minValue, maxValue, isDateUnavailable and isDisabled.
  • months shows 1 or 2 months side by side. Layout and week start follow the locale; use I18nProvider to override.
  • Pass aria-label; keyboard navigation between days is built in.
Example source · show
import { getLocalTimeZone, isWeekend, today } from '@internationalized/date'
import { useLocale } from 'react-aria-components'
import { Calendar, RangeCalendar } from './calendar'

function Bookable() {
  const { locale } = useLocale()
  const now = today(getLocalTimeZone())
  return (
    <Calendar
      aria-label="Appointment date"
      minValue={now}
      isDateUnavailable={(d) => isWeekend(d, locale)}
      defaultValue={now.add({ days: isWeekend(now.add({ days: 1 }), locale) ? 3 : 1 })}
    />
  )
}

export const styles = {
  Single: () => <Calendar aria-label="Date" defaultValue={today(getLocalTimeZone())} />,
  Range: () => {
    const now = today(getLocalTimeZone())
    return <RangeCalendar aria-label="Trip" defaultValue={{ start: now.add({ days: 2 }), end: now.add({ days: 9 }) }} />
  },
  'Two months': () => {
    const now = today(getLocalTimeZone())
    return <RangeCalendar aria-label="Stay" months={2} defaultValue={{ start: now.add({ days: 3 }), end: now.add({ days: 6 }) }} />
  },
  Unavailable: Bookable,
}

Source: packages/ui/src/calendar/calendar.tsx

Catalog

Category
date-time
Priority
Foundation
Primitive
react-aria
React Aria
Calendar