MonthPicker

Inline month, multiple months and months range picker

Import

Usage

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<Date | null>(null);
  return <MonthPicker value={value} onChange={setValue} />;
}

Allow deselect

Set allowDeselect to allow user to deselect current selected date by clicking on it. allowDeselect is disregarded when type prop is range or multiple. When date is deselected onChange is called with null.

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<Date | null>(null);
  return <MonthPicker allowDeselect value={value} onChange={setValue} />;
}

Multiple dates

Set type="multiple" to allow user to pick multiple dates:

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<Date[]>([]);
  return <MonthPicker type="multiple" value={value} onChange={setValue} />;
}

Dates range

Set type="range" to allow user to pick dates range:

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
  return <MonthPicker type="range" value={value} onChange={setValue} />;
}

Single date in range

By default, it is not allowed to select single date as range – when user clicks the same date second time it is deselected. To change this behavior set allowSingleDateInRange prop. allowSingleDateInRange is ignored when type prop is not range.

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
  return (
    <MonthPicker type="range" allowSingleDateInRange value={value} onChange={setValue} />
  );
}

Default date

Use defaultDate prop to set date value that will be used to determine which year should be displayed initially. For example to display 2015 year set defaultDate={new Date(2015, 1)}. If value is not specified, then defaultDate will use new Date(). Month, day, minutes and seconds are ignored in provided date object, only year is used – you can specify any date value.

Note that if you set date prop, then defaultDate value will be ignored.

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<Date | null>(null);
  return <MonthPicker defaultDate={new Date(2015, 1)} value={value} onChange={setValue} />;
}

Controlled date

Set date, and onDateChange props to make currently displayed year and decade controlled. By doing so, you can customize date picking experience, for example, when user selects first date in range, you can add one year to current date value:

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
  const [date, setDate] = useState(new Date());

  const handleChange = (val: [Date | null, Date | null]) => {
    if (val[0] !== null && val[1] === null) {
      setDate((current) => new Date(current.getFullYear() + 1, 1));
    }

    setValue(val);
  };

  return (
    <MonthPicker
      date={date}
      onDateChange={setDate}
      type="range"
      value={value}
      onChange={handleChange}
    />
  );
}

Min and max date

Set minDate and maxDate props to define min and max dates. If previous/next page is not available then corresponding control will be disabled.

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<Date | null>(null);
  return (
    <MonthPicker
      value={value}
      onChange={setValue}
      defaultDate={new Date(2022, 1)}
      minDate={new Date(2022, 1, 1)}
      maxDate={new Date(2022, 8, 1)}
    />
  );
}

Add props to year and month control

You can add props to year and month controls with getYearControlProps and getMonthControlProps functions. Both functions accept date as single argument, props returned from the function will be added to year/month control. For example, it can be used to disable specific control or add styles:

import { useState } from 'react';
import { MonthPicker, MonthPickerProps } from '@mantine/dates';

const getYearControlProps: MonthPickerProps['getYearControlProps'] = (date) => {
  if (date.getFullYear() === new Date().getFullYear()) {
    return {
      style: {
        color: 'var(--mantine-color-blue-filled)',
        fontWeight: 700,
      },
    };
  }

  if (date.getFullYear() === new Date().getFullYear() + 1) {
    return { disabled: true };
  }

  return {};
};

const getMonthControlProps: MonthPickerProps['getMonthControlProps'] = (date) => {
  if (date.getMonth() === 1) {
    return {
      style: {
        color: 'var(--mantine-color-blue-filled)',
        fontWeight: 700,
      },
    };
  }

  if (date.getMonth() === 5) {
    return { disabled: true };
  }

  return {};
};

function Demo() {
  const [value, setValue] = useState<Date | null>(null);
  return (
    <MonthPicker
      value={value}
      onChange={setValue}
      getYearControlProps={getYearControlProps}
      getMonthControlProps={getMonthControlProps}
    />
  );
}

Number of columns

Set numberOfColumns prop to define number of pickers that will be rendered side by side:

Demo is not available on small screens. Make your screen larger to see the demo.

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
  return (
    <MonthPicker type="range" numberOfColumns={2} value={value} onChange={setValue} />
  );
}

Max level

To disallow user going to the decade level set maxLevel="year":

2023
import { MonthPicker } from '@mantine/dates';

function Demo() {
  return <MonthPicker maxLevel="year" />;
}

Size

Size
import { MonthPicker } from '@mantine/dates';

function Demo() {
  return <MonthPicker defaultValue={new Date()} />;
}

Change year and months controls format

Use yearsListFormat and monthsListFormat props to change dayjs format of year/month controls:

import { MonthPicker } from '@mantine/dates';

function Demo() {
  return <MonthPicker monthsListFormat="MM" yearsListFormat="YY" />;
}

Change label format

Use decadeLabelFormat and yearLabelFormat to change dayjs format of decade/year label:

import { useState } from 'react';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  const [value, setValue] = useState<Date | null>(null);
  return (
    <MonthPicker
      decadeLabelFormat="YY"
      yearLabelFormat="YYYY [year]"
      value={value}
      onChange={setValue}
    />
  );
}

Localization

Usually it is better to specify @mantine/dates package locale in DatesProvider, but you can also override locale per component:

import 'dayjs/locale/ru';
import { MonthPicker } from '@mantine/dates';

function Demo() {
  return <MonthPicker locale="ru" />;
}

Accessibility

Aria labels

Set ariaLabels prop to specify aria-label attributes for next/previous controls:

import { MonthPicker } from '@mantine/dates';

function Demo() {
  return (
    <MonthPicker
      ariaLabels={{
        nextDecade: 'Next decade',
        previousDecade: 'Previous decade',
        nextYear: 'Next year',
        previousYear: 'Previous year',
        yearLevelControl: 'Change to decade view',
      }}
    />
  );
}

Year/month control aria-label

Use getYearControlProps/getMonthControlProps to customize aria-label attribute:

import { MonthPicker } from '@mantine/dates';

function Demo() {
  return (
    <MonthPicker
      getYearControlProps={(date) => ({
        'aria-label': `Select year ${date.getFullYear()}`,
      })}
      getMonthControlProps={(date) => ({
        'aria-label': `Select month ${date.getFullYear()}/${date.getMonth()}`,
      })}
    />
  );
}

Keyboard interactions

Note that the following events will only trigger if focus is on month control.

KeyDescription
ArrowRightFocuses next non-disabled month
ArrowLeftFocuses previous non-disabled month
ArrowDownFocuses next non-disabled month in the same column
ArrowUpFocuses previous non-disabled month in the same column