Range Calendar
Preview: Range
Month grid for picking a date (or a range with RangeCalendar), locale-aware and keyboard navigable.
Import
import { Calendar, RangeCalendar } from '@marbleui/ui'This is a style of calendar; see its examples for all variants.
Props
<Calendar>
| Prop | Type | Default | Description |
|---|---|---|---|
| months | 1 | 2 | 1 | Show N months side by side. |
Also accepts React Aria props (100).
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
RangeCalendar picks a start and end date on an always-visible month grid, drawn as one band. It is exported next to Calendar; for a range inside a form field with a popover, use DateRangePicker.
import { today, getLocalTimeZone } from '@internationalized/date'
const t = today(getLocalTimeZone())
<RangeCalendar
aria-label="Hotel stay"
months={2}
minValue={t}
defaultValue={{ start: t.add({ days: 3 }), end: t.add({ days: 6 }) }}
onChange={setStay}
/>
- A range takes two presses: the first sets the start, the band follows the pointer or keyboard focus, the second sets the end. With a mouse or touch, dragging an existing start or end moves that edge.
- Keyboard: arrow keys move, Enter or Space starts and finishes the range. Screen readers are prompted to start and finish the selection.
isDateUnavailable(date, anchor)also receives the first-picked date, so you can cap the length:anchor != null && date.compare(anchor.add({ days: 14 })) > 0. A range can’t cross an unavailable day unlessallowsNonContiguousRangesis set.- With
months={2}the arrows page two months at a time;pageBehavior="single"moves one.
Example source · show· hide
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
- Core
- Primitive
- react-aria
- React Aria
- RangeCalendar