Patterns
Static Month Grid
When to use:
- one known month is enough, for example picking a day inside a billing period
Composition notes:
- use
DayPickerLayoutand passmonthexplicitly, so the grid does not depend on today - constrain the period with
fromandtoinstead of hiding days
Trade-offs:
- simple and stable
- no navigation; use a scroller or
Calendarwhen users move between months
import { DayPicker, DayPickerCell, DayPickerLayout, Text } from '@vega-ui/react';
import { useState } from 'react';
const dateFormat = new Intl.DateTimeFormat('en-US', { month: 'long', day: 'numeric', timeZone: 'UTC' });
export default function StaticMonthGrid() {
const [day, setDay] = useState<string | null>(null);
return (
<div style={{ display: 'grid', gap: 'var(--spacing-6)', justifyItems: 'start', width: '100%' }}>
<DayPicker
aria-label='Payment day, November 2026'Swipable Month Paging
When to use:
- users move between months with swipe or snap paging and the app draws its own header
Composition notes:
- use
DayPickerScrollerwithDayPickerScrollerContentandDayPickerScrollerLayout onChangePeriodreports the first day of the month scrolled into view; store it and pass it back asmonth, so the header and the grid agree- keep
activein state as well and move it into the new month, otherwise the grid can lose its tab stop - reach for
Calendarwhen the standard header, month view, and year view are enough
Trade-offs:
- tactile, and any header layout is possible
- the app owns navigation state that
Calendarwould handle
import {
DayPicker,
DayPickerCell,
DayPickerScroller,
DayPickerScrollerContent,
DayPickerScrollerLayout,
Icon,
IconButton,
Text,
} from '@vega-ui/react';
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import { useState } from 'react';Custom Grid Rendering
When to use:
- the row and cell structure itself must change, which a cell template cannot do
Composition notes:
- build rows with
createDayPickerGridinstead of reimplementing date math; pass the samecalendaras the picker dateisundefinedfor an empty overflow cell;dayis the day number in the calendar system- set
disabledandexcludedon cells outside the month, as the built-in cell does - here a Monday-to-Friday grid: weekend cells are not rendered, and weeks without a workday of the month are dropped
Trade-offs:
- full control over markup
- labels, week start, and overflow handling are the app's job; prefer a cell template when only the content changes
import {
CalendarBaseWeekLabel,
CalendarBaseWeekLabels,
DayPicker,
DayPickerItem,
DayPickerRow,
DayPickerRowGroup,
createDayPickerGrid,
} from '@vega-ui/react';
const MONTH = '2026-11-01';
const WORK_DAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];Cell Template
When to use:
- day cells need extra content such as a price, a status, or a count
Composition notes:
- children of
DayPickerLayoutandDayPickerScrollerLayoutare rendered once per day inside a cell context - read the day with
useDayPickerCellContext():{ col, date, fields, label, inMonth };dateisundefinedfor an empty overflow cell - render the content inside
DayPickerCellso the cell keeps selection, focus, and disabled states - take day numbers from
labelorfields, never from the ISOdatestring; they differ in non-Gregorian calendars - look data up by
date, which is the same in every calendar system - extra content that is only visual (dots, colors) needs words in the cell's
aria-label
Trade-offs:
- keeps the grid, keys, and keyboard behavior of the layout
- richer cells can crowd small sizes
import {
DayPicker,
DayPickerCell,
DayPickerLayout,
useDayPickerCellContext,
} from '@vega-ui/react';
const events: Record<string, string[]> = {
'2026-11-04': ['Design review', 'Sprint planning'],
'2026-11-12': ['Release 3.2'],
'2026-11-18': ['Team offsite', 'Retro', 'Demo day'],
};Comparison
Quick Decision Rule
Use DayPicker when you need low-level day-grid selection behavior. Use Calendar when you need a higher-level calendar experience.
DayPicker vs Calendar
- Use
DayPickerfor low-level day-grid composition. - Use
Calendarfor the higher-level calendar subsystem.
DayPicker vs MonthPicker / YearPicker
- Use
DayPickerfor actual dates. - Use
MonthPickerorYearPickerfor month/year selection surfaces.
Choose This Component When
- you are extending calendar-family internals
- you need day-grid selection with custom composition
Do Not Choose This Component When
- you want a higher-level calendar abstraction with less manual composition
Troubleshooting
The Rendered Month Does Not Match The Expected Period
Symptom
The UI shows a month grid, but it is not the period users expected.
Likely Cause
The visible month, the calendar system, or the scroller's defaultMonth are not aligned.
How To Verify
- inspect the effective
month,calendar, and the value passed toonChangePeriod
Fix
Use one YYYY-MM-DD month as the source of truth and pass the same calendar to every part that renders it.
Custom Day Rendering Loses Selection Or Focus Clarity
Symptom
Dates still work logically, but users cannot tell which day is active or selected.
Likely Cause
Custom rendering discarded important visual state.
How To Verify
- test focus, selected, disabled, and excluded states in the custom layout
Fix
Preserve the item state affordances from the default day item pattern.
Scrollable Month Paging Feels Fragile
Symptom
Swiping between months works sometimes, but period labels or focus feel unstable.
Likely Cause
Scroller period mapping and rendered month content are not synchronized tightly enough.
How To Verify
- log the month passed to
onChangePeriodwhile paging
Fix
Derive labels from the month reported by onChangePeriod instead of computing it from the scroller index.