Calendar

A calendar component for selecting dates and date ranges.

1<Calendar />

Anatomy

Import and assemble the component:

1import { Calendar, RangePicker, DatePicker } from '@raystack/apsara'
2
3<Calendar />
4
5<RangePicker />
6
7<DatePicker />

Usage

Calendar is the grid itself. DatePicker and RangePicker wrap it in a field and a popover, and all three share the props below.

Layout and appearance

Number of months, dropdown nav, loading state, footer.

1<Calendar
2 numberOfMonths={2}
3 defaultMonth={new Date(2025, 5, 1)}
4 showWeekNumber={false}
5 weekStartsOn={1}
6 showOutsideDays={false}
7/>

Behaviour and data

Tooltips, disabled days, timezone, controlled month navigation.

1<Calendar
2 showTooltip
3 tooltipMessages={{
4 "15-06-2026": "Holiday",
5 "20-06-2026": "Team off-site",
6 }}
7/>

Custom date information

You can display custom components above each date using the dateInfo prop. The keys should be date strings in "dd-MM-yyyy" format, and the values are React components that will be rendered above the date number.

1<Calendar
2 numberOfMonths={2}
3 dateInfo={{
4 [dayjs().format("DD-MM-YYYY")]: (
5 <Flex
6 align="center"
7 gap={2}
8 style={{
9 fontSize: "8px",
10 color: "var(--rs-color-foreground-base-secondary)",
11 }}
12 >
13 <Info style={{ width: "8px", height: "8px" }} />
14 <Text style={{ fontSize: "8px" }} color="secondary">
15 25%

Range picker

Selects a date range across two inputs. The grid uses a state machine that branches on the current from / to:

  • Empty: first click sets from and advances focus to the end input.
  • Only from set: clicking a later date completes the range and closes the popover; clicking an earlier date resets from.
  • Both set: clicking again restarts: the new date becomes from, to clears.

onSelect fires on every step (the shape is { from?: Date; to?: Date }, partial during interaction). Gate on range.to if you only want the completed-range event.

1<RangePicker />

Date picker

Single-date selection with a typable input. The popover opens on focus; pressing Enter, blurring, or clicking outside commits the value and fires onSelect.

1<DatePicker slotProps={{ input: { size: "medium" } }} />

Controlled

Pass selected with onSelect to own the date. This is needed when the value comes from a form or has to be set from elsewhere, like a Today button.

1(function ControlledCalendar() {
2 const [date, setDate] = React.useState(new Date());
3
4 return (
5 <Flex direction="column" align="center" gap={5}>
6 <Calendar mode="single" selected={date} onSelect={setDate} />
7 <Flex align="center" gap={4}>
8 <Text size="small" variant="secondary">
9 {date ? dayjs(date).format("D MMM YYYY") : "nothing selected"}
10 </Text>
11 <Button
12 size="small"
13 variant="outline"
14 onClick={() => setDate(new Date())}
15 >

API Reference

The bare grid, and the two pickers built on top of it.

Calendar

Renders a standalone calendar for date selection.

Prop

Type

RangePicker

The RangePicker exposes its startInput, endInput, calendar and popover slots through the slotProps prop.

Prop

Type

DatePicker

The DatePicker exposes its input, calendar and popover slots through the slotProps prop.

Prop

Type

Slots

Every rendered part carries a stable data-slot attribute for styling and testing:

SlotElement
calendarThe root calendar surface
calendar-nav-previousThe previous-month navigation button
calendar-nav-nextThe next-month navigation button
calendar-dropdownThe month/year dropdown trigger (when captionLayout="dropdown")
calendar-dropdown-contentThe dropdown's option list (when the dropdown is open)
calendar-month-gridWrapper around the day grid and its skeleton
calendar-grid-tableThe <table> that holds the days
calendar-grid-skeletonThe loading skeleton shown over the grid
calendar-dayThe <button> for a single day
calendar-day-infoExtra info shown inside a day (when dateInfo resolves for that day)
calendar-day-numberThe day number inside a day button
calendar-day-tooltipThe tooltip shown on hover (when showTooltip and a message exists)
date-picker-triggerThe <div> wrapping the DatePicker trigger
date-picker-inputThe DatePicker's text <input>
date-picker-positionerThe popover positioner for the DatePicker
date-picker-contentThe DatePicker popover content that holds the calendar
range-picker-triggerThe <div> wrapping the RangePicker trigger
range-picker-trigger-groupThe row that groups the start and end inputs
range-picker-start-inputThe RangePicker's start date <input>
range-picker-end-inputThe RangePicker's end date <input>
range-picker-positionerThe popover positioner for the RangePicker
range-picker-contentThe RangePicker popover content that holds the calendar
range-picker-footerThe footer below the calendar (when footer is set)

Accessibility

  • Supports keyboard navigation between dates with arrow keys
  • Uses aria-label attributes for date cells
  • Selected and disabled dates are announced to screen readers