Calendar

Import
import { Calendar } from "reshaped";
import type { CalendarProps } from "reshaped";
Supports date and month selection
Works with single and range date selection
Can be controlled and uncontrolled
Navigation is keyboard and screen reader accessible
Supports rendering localization


Calendar is designed to be functional without passing any properties by default, which will render the current month and use a single date selection. You can add an onChange handler to update the selection in your state. When user clicks the selected month title, it also switches to the month selection view which lets users navigate the years much faster.

<Calendar onChange={console.log} />

You can pick the default month you want to render with the defaultMonth property.

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

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

Calendar supports controlled and uncontrolled behaviour. By default, Calendar is uncontrolled and lets you 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. That will give you complete control of the component value and will stop handling the value automatically. You will have to update the state using the onChange handler and will be able to add custom logic before that happens.

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

Calendar supports selecting 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 if you're using them.

<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. It will disable the dates outside the passed min and max values and disable the navigation to the 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 is using English localization as a default but you pass your own translations using the renderMonthLabel, renderWeekDay, renderSelectedMonthLabel properties. For example, we're using 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 changing 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 exampl, 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>
  );
}

Calendar comes with default set of aria labels provided in English. In case you need to localize them or format 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 as regular buttons and are focusable during the Tab navigation. Only one date or month from the selection can be focused with Tab and then users can navigate the rendered list with arrow keys. Additionally Calendar manages the focus when switching in between modes or during navigation, to make sure focus always stays on the relevant element.