Calendar

Import
import { Calendar } from "reshaped";
import type { CalendarProps } from "reshaped";

Calendar is designed to be functional without passing any properties by default, rendering the current month with a single date selection. You can add an onChange handler to update the selection in your state. When the user clicks the selected month title, it switches to the month selection view, allowing users to navigate the years more quickly.

<Calendar onChange={console.log} />

You can specify the default month to render using the defaultMonth property.

<Calendar defaultMonth={new Date(2023, 0)} />

Note that when creating a date in the example above, the month argument is a month index and it starts from 0.

Calendar supports both controlled and uncontrolled behavior. By default, Calendar is uncontrolled and allows you to define its default state using the defaultValue property. In this case, all change events are handled automatically.

<Calendar
  defaultMonth={new Date(2023, 0)}
  defaultValue={new Date(2023, 0, 10)}
/>

If you need to control the state of the Calendar manually, you can use the value property. This gives you complete control over the component value and stops automatic value handling. You will need to update the state using the onChange handler and can add custom logic before that happens.

<Calendar defaultMonth={new Date(2023, 0)} value={new Date(2023, 0, 10)} />

Calendar supports selecting a start and end date instead of just a single date selection. To enable this selection mode, set the range flag to true and update the format of the defaultValue or value properties to a { start, end } object.

<Calendar
  range
  defaultMonth={new Date(2023, 0)}
  defaultValue={{ start: new Date(2023, 0, 10), end: new Date(2023, 0, 14) }}
/>

You can set min and max date values to control the selection boundaries. This will disable dates outside the passed min and max values and disable navigation to months that don't have any enabled dates.

<Calendar
  range
  defaultMonth={new Date(2023, 0)}
  min={new Date(2023, 0, 5)}
  max={new Date(2023, 2, 17)}
/>

Calendar uses English localization by default, but you can pass your own translations using the renderMonthLabel, renderWeekDay, and renderSelectedMonthLabel properties. For example, we're using the toLocaleDateString method to translate all Calendar labels to Dutch.

<Calendar
  defaultMonth={new Date(2023, 11)}
  renderMonthLabel={({ date }) =>
    date.toLocaleDateString("nl", { month: "short" })
  }
  renderSelectedMonthLabel={({ date }) =>
    date.toLocaleDateString("nl", { month: "long", year: "numeric" })
  }
  renderWeekDay={({ date }) =>
    date.toLocaleDateString("nl", { weekday: "short" })
  }
/>

You can also change the rendering of the weekdays order by setting the firstWeekDay property. For example, here we set the week to start with Sunday.

<Calendar defaultMonth={new Date(2023, 11)} firstWeekDay={0} />

You can combine Calendar with other components to implement custom date selection experiences. For example, here we're combining it with Popover and InputSelect to implement a regular datepicker.

function DatePicker() {
  const [date, setDate] = React.useState(null);
  const toggle = useToggle();

  const handleCalendarChange = (args) => {
    setDate(args.value);
    toggle.deactivate();
  };

  return (
    <View width="360px" maxWidth="100%">
      <Popover
        position="bottom"
        width="trigger"
        active={toggle.active}
        onOpen={toggle.activate}
        onClose={toggle.deactivate}
      >
        <Popover.Trigger>
          {(attributes) => (
            <Select attributes={attributes} placeholder="Select a date">
              {date &&
                date.toLocaleDateString("nl", {
                  day: "numeric",
                  month: "long",
                  year: "numeric",
                })}
            </Select>
          )}
        </Popover.Trigger>
        <Popover.Content>
          <Calendar onChange={handleCalendarChange} value={date} />
        </Popover.Content>
      </Popover>
    </View>
  );
}
  • ArrowLeft - move date focus to the previous date
  • ArrowRight - move date focus to the next date
  • ArrowUp - move date focus to the previous week
  • ArrowDown - move date focus to the next week
  • Enter / Space - select the focused date
  • Calendar comes with a default set of aria labels provided in English. In case you need to localize them or format them differently, you can use the following properties:
<Calendar
  previousYearAriaLabel="Previous year"
  nextYearAriaLabel="Next year"
  nextMonthAriaLabel="Next month"
  previousMonthAriaLabel="Previous month"
  renderDateAriaLabel={({ date }) => "..."}
  renderMonthAriaLabel={({ month }) => "..."}
  monthSelectionAriaLabel="Select a month"
/>
  • Calendar supports keyboard and screen reader navigation. Navigation controls work like regular buttons and are focusable during Tab navigation. Only one date or month from the selection can be focused with Tab, and users can navigate the rendered list with arrow keys.
  • Calendar manages focus when switching between modes or during navigation, ensuring that focus always stays on the relevant element.