Calendar

Calendar provides a customizable calendar interface for single date selection.

The component is built with accessibility in mind and follows ARIA best practices for calendar widgets. It provides keyboard navigation, screen reader support, and customizable labels for internationalization.

import { Calendar } from '@wordpress/ui';

View on Storybook

View source on GitHub

PropsPermalink to this section

NameDefaultDescription
role'application'

AriaRole | undefined

The ARIA role for the calendar’s root element.

The default application role helps assistive technologies pass calendar navigation keys to the component. Its accessible name includes the current month.

Changing this role can affect screen-reader keyboard navigation. Only override it for a tested composition. Apply roles that require additional behavior, such as dialog, to a wrapper.

requiredfalse

boolean

Whether the selection is required. When true, there always needs to be a date selected.

defaultMonthThe current month

Date

The initial month to show in the calendar view (uncontrolled).

month

Date

The month displayed in the calendar view (controlled). Use together with onMonthChange to change the month programmatically.

numberOfMonths1

number

The number of months displayed at once.

showOutsideDaysfalse

boolean

When true, days from adjacent months are shown in the grid and receive the outside modifier and the class.

fixedWeeksfalse

boolean

When true, the calendar always shows a fixed number of weeks (e.g. 6) so the grid height does not change between months.

startMonth

Date

The earliest month to start the month navigation.

endMonth

Date

The latest month to end the month navigation.

autoFocus

boolean

Focus the first selected day (if set) or today’s date (if not disabled).

Use this prop when the calendar should receive initial focus as it opens, such as in a calendar popover. Do not use it to move focus after updates to an open calendar.

disabled

Matcher | Matcher[] | undefined

Specify which days are disabled. Using true will disable all dates.

disableNavigation

boolean

Disable the navigation buttons.

labels

{ labelNav?: (() => string) | undefined; labelGrid?: ((date: Date) => string) | undefined; labelGridcell?: ((date: Date, modifiers?: Modifiers | undefined) => string) | undefined; labelNext?: ((month: Date | undefined) => string) | undefined; labelPrevious?: ((month: Date | undefined) => string) | undefined; labelDa...

Use custom labels, useful for translating the component.

For a correct localized experience, consumers should make sure the locale used for translated labels and date text is consistent.

localeThe `enUS` locale from `date-fns/locale`

string | Locale | undefined

A BCP 47 locale code or date-fns locale object used to localize date text, numerals, the default text direction, and the first day of the week.

The locale code derives the first day of the week when the browser provides that information, whether passed directly or through a date-fns locale object. Use weekStartsOn to override this default.

Invalid or unsupported locale codes fall back to en-US for date text. A date-fns locale object with an unsupported code retains its own first-day setting.

For a correct localized experience, consumers should make sure the locale used for translated labels and date text is consistent.

The calendar always uses a Gregorian date grid. The locale does not change the underlying calendar system.

weekStartsOnBased on the `locale` prop when available

0 | 1 | 2 | 3 | 4 | 5 | 6

The index of the first day of the week (0 – Sunday). Overrides the locale’s one.

onMonthChange

(month: Date) => void

Event fired when the user navigates between months.

timeZone

string

The time zone (IANA or UTC offset) to use in the calendar.

See Wikipedia for the possible values.

When working with time zones, use the TZDate object from the @date-fns/tz package instead of the native Date object.

style

CSSProperties

CSS style to apply to the element.

className

string

CSS class name to apply to the element.

render

ComponentRenderFn<HTMLAttributesWithRef<any>> | ReactElement<Record<string, unknown>, string | JSXElementConstructor<any>> | undefined

Replaces the component’s default HTML element using a given React element, or a function that returns a React element.

value

Date | null | undefined

The selected date (controlled). Use null when there is no selection. To render an uncontrolled calendar, use defaultValue instead.

onValueChange

OnValueChangeHandler<Date | null>

Event handler called when the selected date changes.

defaultValue

Date

The initially selected date (uncontrolled).

ExamplesPermalink to this section

DefaultPermalink to this section

const Default = () => <Calendar onMonthChange={fn()} onValueChange={fn()} endMonth={ toDate( endMonth ) } />;

Disabled DatesPermalink to this section

const DisabledDates = () => <Calendar
    onMonthChange={fn()}
    onValueChange={fn()}
    disabled={DISABLED_DATES_SAMPLE}
    endMonth={ toDate( endMonth ) } />;

With Selected Date And MonthPermalink to this section

const WithSelectedDateAndMonth = () => <Calendar
    onMonthChange={fn()}
    onValueChange={fn()}
    defaultValue={firstDayOfNextMonth}
    defaultMonth={firstDayOfNextMonth}
    endMonth={ toDate( endMonth ) } />;

With Outside DaysPermalink to this section

Shows days from adjacent months in the grid. Outside days use a lighter style and are still interactive. Use fixedWeeks to keep the grid height constant.

const WithOutsideDays = () => <Calendar
    onMonthChange={fn()}
    onValueChange={fn()}
    showOutsideDays
    fixedWeeks
    endMonth={ toDate( endMonth ) } />;

With Time ZonePermalink to this section

When working with time zones, use the TZDate object from the @date-fns/tz package instead of the native Date object.

const WithTimeZone = () => {
    const [ selected, setSelected ] = useState< TZDate | null >( null );

    useEffect( () => {
        setSelected(
            // Select one week from today every time the time zone changes.
            new TZDate(
                new Date().setDate( new Date().getDate() + 7 ),
                args.timeZone
            )
        );
    }, [ args.timeZone ] );

    return (
        <>
            <Calendar
                onMonthChange={fn()}
                timeZone="Pacific/Auckland"
                endMonth={ toDate( endMonth ) }
                value={ selected }
                onValueChange={ ( selectedDate, ...rest ) => {
                    setSelected(
                        selectedDate
                            ? new TZDate( selectedDate, args.timeZone )
                            : null
                    );
                    args.onValueChange?.( selectedDate, ...rest );
                } }
                disabled={ [
                    {
                        // Disable any date before today
                        before: new TZDate( new Date(), args.timeZone ),
                    },
                ] } />
            <p>Calendar set to { args.timeZone ?? 'current' }timezone,
                                    disabling selection for all dates before today, and starting
                                    with a default date of 1 week from today.
                                </p>
        </>
    );
};