Skip to content
v2.5.0
English
Русский
Documentation

MonthPicker

MonthPicker is the grid-based month-selection subsystem used directly or as part of the calendar family.
January
February
March
April
May
June
July
August
September
October
November
December
month-picker.tsx · 5 lines
import { MonthPicker, MonthPickerCell, MonthPickerLayout } from '@vega-ui/react';

<MonthPicker aria-label='Month, 2026' locale='en-US' year='2026-01-01' defaultSelected='2026-11-01' style={{ width: '100%' }}>
  <MonthPickerLayout><MonthPickerCell /></MonthPickerLayout>
</MonthPicker>
Browser support
Widely available
  • Chrome 111
  • Edge 111
  • Firefox 113
  • Safari 15.4
  • Safari on iOS 15.4
Bundle size
Tested in
17 tests

Summary

MonthPicker is the grid-based month-selection subsystem used directly or as part of the calendar family. It builds on DataGridPicker and exposes month-layout parts and helper-driven custom rendering.

Imports

import {
  MonthPicker,
  MonthPickerCell,
  MonthPickerItem,
  MonthPickerLayout,
  MonthPickerRow,
  MonthPickerRowGroup,
  createMonthPickerGrid,
  useMonthPickerCellContext,
  useMonthPickerContext,
  type MonthPickerCellContextData,
  type MonthPickerCellProps,
  type MonthPickerItemProps,
  type MonthPickerLayoutProps,
  type MonthPickerProps,
  type MonthPickerRowGroupProps,
  type MonthPickerRowProps,
} from '@vega-ui/react';

Exported Types

  • MonthPickerProps
  • MonthPickerLayoutProps
  • MonthPickerRowGroupProps
  • MonthPickerRowProps
  • MonthPickerItemProps
  • MonthPickerCellProps
  • MonthPickerCellContextData

Minimal Composition

en-US
ru-RU
ar-EG
he-IL
minimal-composition.tsx · 13 lines
import { MonthPicker, MonthPickerCell, MonthPickerLayout } from '@vega-ui/react';

export const locales = ['en-US', 'ru-RU', 'ar-EG', 'he-IL'];

export default function MinimalComposition({ locale = 'en-US' }: { locale?: string }) {
  return (
    <MonthPicker aria-label='Month, 2026' locale={locale} year='2026-01-01' style={{ width: '100%' }}>
      <MonthPickerLayout>
        <MonthPickerCell />
      </MonthPickerLayout>
    </MonthPicker>
  );

Required Parts

  • MonthPicker: root month-selection subsystem

Optional Parts

  • MonthPickerLayout
  • MonthPickerRowGroup
  • MonthPickerRow
  • MonthPickerItem
  • MonthPickerCell: the cell, placed as the template of the layouts

Composition Order

  1. MonthPicker
  2. either MonthPickerLayout with a cell template as children (<MonthPickerCell /> or a custom one) or custom row/item composition

Variants

  • Selection: single, multiple, range
  • Layout density: cols; rows follow the number of months in the year
  • Period: explicit year (a YYYY-MM-DD string of any day in it) or the current year
  • Locale and calendar system: locale and calendar props, defaulting to the runtime locale and the Gregorian calendar
  • Label formatting: locale-driven month names

Edge Cases

  • Locale and month-label format should stay consistent with the rest of the date system.
  • Custom layouts should preserve selection and disabled affordances from the picker primitives.
  • This is a low-level month selector, not necessarily the final consumer-facing calendar experience.

Common Mistakes

  • Hardcoding month labels while the rest of the app is localized.
  • Recreating the month grid manually instead of using createMonthPickerGrid.
  • Assuming every year has 12 months or that months are zero-based numbers.
  • Treating it as a generic content grid instead of a month-selection system.

Examples

Basic

Basic: months of one year

MonthPickerLayout renders all months of the year given by year, any ISO day inside it. Each cell is keyed by the first day of its month, so defaultSelected is '2026-03-01' for March. The grid has no visible title, so it gets an aria-label.

months-of-one-year.tsx · 11 lines
import { MonthPicker, MonthPickerCell, MonthPickerLayout } from '@vega-ui/react';

export default function MonthsOfOneYear() {
  return (
    <MonthPicker aria-label='Start month, 2026' locale='en-US' year='2026-01-01' defaultSelected='2026-03-01' style={{ width: '100%' }}>
      <MonthPickerLayout>
        <MonthPickerCell />
      </MonthPickerLayout>
    </MonthPicker>
  );
}

Controlled/Stateful

Controlled/Stateful: billing month with year navigation

The selected month and the visible year are separate pieces of state: the buttons change the year, a click changes the month, and the line below shows the result. MonthPicker keeps its active cell when year changes, so the buttons move active into the new year as well.

billing-month-with-year-navigation.tsx · 52 lines
import {
  Icon,
  IconButton,
  MonthPicker,
  MonthPickerCell,
  MonthPickerLayout,
  Text,
} from '@vega-ui/react';
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import { useState } from 'react';

const monthFormat = new Intl.DateTimeFormat('en-US', { month: 'long', year: 'numeric', timeZone: 'UTC' });

Form/Integration

Form/Integration: report period

selection='range' picks a period of months. Cells are month starts, so the form submits the start as is and turns the end into the last day of its month; FormData reads both back, the empty check reuses the linked hint, and reset clears the state.

report-period.tsx · 81 lines
import {
  Button,
  Fieldset,
  FieldsetLegend,
  HelperText,
  MonthPicker,
  MonthPickerCell,
  MonthPickerLayout,
  Text,
} from '@vega-ui/react';
import { FormEvent, useId, useState } from 'react';

Layout/Overlay

Layout/Overlay: month filter in a popover

A compact month grid behind a trigger, for a statement or dashboard filter. The popover is controlled and closes when a month is picked; months after the latest statement are disabled with to.

month-filter-in-a-popover.tsx · 49 lines
import {
  Button,
  Icon,
  MonthPicker,
  MonthPickerCell,
  MonthPickerLayout,
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@vega-ui/react';
import { ChevronDown } from '@vega-ui/icons';
import { useState } from 'react';

Error

Error: period too long

The picker does not limit the length of a range. The app counts the months and turns the hint linked to the grid into an error while the period is longer than six months.

period-too-long.tsx · 51 lines
import {
  HelperText,
  MonthPicker,
  MonthPickerCell,
  MonthPickerLayout,
} from '@vega-ui/react';
import { useId, useState } from 'react';

const MAX_MONTHS = 6;

function countMonths(from?: string, to?: string) {
  if (!from || !to) return 0;

Disabled

Disabled: months without data

from and to disable months outside the period that has data, here June 2025 to October 2026. The rule is written next to the grid and linked with aria-describedby; the disabled state alone does not explain it.

months-without-data.tsx · 30 lines
import {
  HelperText,
  MonthPicker,
  MonthPickerCell,
  MonthPickerLayout,
} from '@vega-ui/react';
import { useId } from 'react';

export default function MonthsWithoutData() {
  const hintId = useId();

  return (

Disabled: specific months

An array of month starts disables exactly those months, for example the months a seasonal venue is closed.

specific-months.tsx · 31 lines
import {
  HelperText,
  MonthPicker,
  MonthPickerCell,
  MonthPickerLayout,
} from '@vega-ui/react';
import { useId } from 'react';

const closedMonths = ['2026-01-01', '2026-02-01', '2026-12-01'];

export default function SpecificMonths() {
  const hintId = useId();

Edge

Edge: 13-month year

With a calendar system from createCalendarSystem (see Calendar System Adapter), the grid shows the months of that calendar. The Hebrew year 5784 is a leap year with 13 months, Adar I and Adar II included, so the last row is not full. year='2024-03-15' is any day of that year; its first month starts on 2023-09-16, and every cell key is the ISO day its month starts on, not a Gregorian month start: Adar I is '2024-02-10'.

13-month-year.tsx · 28 lines
import { createCalendarSystem } from '@vega-ui/i18n';
import { MonthPicker, MonthPickerCell, MonthPickerLayout, Text } from '@vega-ui/react';
import { useState } from 'react';

const hebrewCalendar = createCalendarSystem('hebrew');

export default function ThirteenMonthYear() {
  const [month, setMonth] = useState<string | null>('2024-02-10');

  return (
    <div style={{ display: 'grid', gap: 'var(--spacing-6)', justifyItems: 'start', width: '100%' }}>
      <MonthPicker

Anatomy

Overview

MonthPicker wraps DataGridPicker for month values and exposes row, item, and layout parts for static month grids.

Required Parts

MonthPicker

Required. Owns the month selection state model through DataGridPicker.

Optional Parts

MonthPickerLayout

Optional default month-grid renderer.

MonthPickerCell

Cell template. Children of MonthPickerLayout are required and rendered once per month inside a cell context read by useMonthPickerCellContext(); usually <MonthPickerCell />. Put custom content inside MonthPickerCell to keep selection, focus, and disabled states.

MonthPickerRowGroup, MonthPickerRow, MonthPickerItem

Optional low-level month-grid composition parts.

Composition Order

  1. MonthPicker
  2. either MonthPickerLayout or custom row/item composition

Valid Composition Patterns

The explicit parts: MonthPickerRowGroup › MonthPickerRow › MonthPickerItem, built from createMonthPickerGrid. MonthPickerLayout with a MonthPickerCell template renders the same structure; see Minimal Composition.

custom-grid-rendering.tsx · 30 lines
import {
  MonthPicker,
  MonthPickerItem,
  MonthPickerRow,
  MonthPickerRowGroup,
  createMonthPickerGrid,
} from '@vega-ui/react';

const YEAR = '2026-01-01';
const narrowFormat = new Intl.DateTimeFormat('en-US', { month: 'narrow', timeZone: 'UTC' });
const longFormat = new Intl.DateTimeFormat('en-US', { month: 'long', timeZone: 'UTC' });
const rows = createMonthPickerGrid({ year: YEAR, cols: 6 });

Invalid Composition Patterns

Month labels hardcoded inconsistently with the rest of the app

Localization and date semantics drift apart.

Layout rebuilt without helper functions

Month ordering and selection semantics become easier to break.