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
- Oklab and OkLCh — comes from the design tokens
- Logical properties
- :focus-visible
- :where()
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
MonthPickerPropsMonthPickerLayoutPropsMonthPickerRowGroupPropsMonthPickerRowPropsMonthPickerItemPropsMonthPickerCellPropsMonthPickerCellContextData
Minimal Composition
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
MonthPickerLayoutMonthPickerRowGroupMonthPickerRowMonthPickerItemMonthPickerCell: the cell, placed as the template of the layouts
Composition Order
MonthPicker- either
MonthPickerLayoutwith 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(aYYYY-MM-DDstring of any day in it) or the current year - Locale and calendar system:
localeandcalendarprops, 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.
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.
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.
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.
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.
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.
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.
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'.
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%' }}>
<MonthPickerAnatomy
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
MonthPicker- either
MonthPickerLayoutor 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.
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.