Перейти к содержимому
v2.5.0
English
Русский
Документация

DayPicker

DayPicker — низкоуровневая подсистема сетки дней, на которой строится стек календаря.

Паттерны

Статичная сетка месяца

Когда использовать:

  • достаточно одного известного месяца, например при выборе дня внутри расчётного периода

Заметки по композиции:

  • используйте DayPickerLayout и передавайте month явно, чтобы сетка не зависела от сегодняшней даты
  • ограничивайте период через from и to, а не скрывайте дни

Компромиссы:

  • просто и стабильно
  • нет навигации; используйте скроллер или Calendar, когда пользователи переходят между месяцами
static-month-grid.tsx · 29 строк
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'

Перелистывание месяцев свайпом

Когда использовать:

  • пользователи переходят между месяцами свайпом или постраничной прокруткой, а приложение рисует собственный заголовок

Заметки по композиции:

  • используйте DayPickerScroller с DayPickerScrollerContent и DayPickerScrollerLayout
  • onChangePeriod сообщает первый день месяца, прокрученного в область видимости; сохраните его и передайте обратно как month, чтобы заголовок и сетка совпадали
  • храните в состоянии и active и переносите его в новый месяц, иначе сетка может потерять точку табуляции
  • берите Calendar, когда достаточно стандартного заголовка и представлений месяца и года

Компромиссы:

  • тактильно, и возможна любая раскладка заголовка
  • приложение само управляет состоянием навигации, которое взял бы на себя Calendar
visible-month-with-own-navigation.tsx · 67 строк
import {
  DayPicker,
  DayPickerCell,
  DayPickerScroller,
  DayPickerScrollerContent,
  DayPickerScrollerLayout,
  Icon,
  IconButton,
  Text,
} from '@vega-ui/react';
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import { useState } from 'react';

Собственный рендер сетки

Когда использовать:

  • должна измениться сама структура строк и ячеек, чего не может шаблон ячейки

Заметки по композиции:

  • стройте строки через createDayPickerGrid, а не пишите математику дат заново; передавайте тот же calendar, что и компоненту
  • date равен undefined для пустой ячейки за пределами месяца; day — номер дня в календарной системе
  • задавайте disabled и excluded ячейкам вне месяца, как это делает встроенная ячейка
  • здесь сетка с понедельника по пятницу: ячейки выходных не рендерятся, а недели без рабочих дней месяца отброшены

Компромиссы:

  • полный контроль над разметкой
  • подписи, начало недели и обработка дней соседних месяцев — задача приложения; если меняется только содержимое, предпочитайте шаблон ячейки
custom-grid-rendering.tsx · 38 строк
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'];

Шаблон ячейки

Когда использовать:

  • ячейкам дней нужно дополнительное содержимое, например цена, статус или счётчик

Заметки по композиции:

  • дочерние элементы DayPickerLayout и DayPickerScrollerLayout рендерятся по разу на каждый день внутри контекста ячейки
  • читайте день через useDayPickerCellContext(): { col, date, fields, label, inMonth }; date равен undefined для пустой ячейки за пределами месяца
  • рендерите содержимое внутри DayPickerCell, чтобы ячейка сохраняла состояния выбора, фокуса и отключения
  • берите номера дней из label или fields, а не из ISO-строки date; в негригорианских календарях они различаются
  • ищите данные по date — он одинаков в любой календарной системе
  • чисто визуальному содержимому (точки, цвет) нужны слова в aria-label ячейки

Компромиссы:

  • сохраняет сетку, ключи и поведение клавиатуры раскладки
  • насыщенные ячейки могут теснить содержимое на малых размерах
cell-template.tsx · 38 строк
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'],
};

Сравнение

Быстрое правило выбора

Используйте DayPicker, когда нужно низкоуровневое поведение выбора в сетке дней. Используйте Calendar, когда нужен календарь более высокого уровня.

DayPicker или Calendar

  • Используйте DayPicker для низкоуровневой композиции сетки дней.
  • Используйте Calendar для календарной подсистемы более высокого уровня.

DayPicker или MonthPicker / YearPicker

  • Используйте DayPicker для конкретных дат.
  • Используйте MonthPicker или YearPicker для выбора месяца или года.

Выбирайте этот компонент, когда

  • вы расширяете внутренности семейства календарей
  • нужен выбор в сетке дней с собственной композицией

Не выбирайте этот компонент, когда

  • нужна календарная абстракция более высокого уровня с меньшим объёмом ручной композиции

Решение проблем

Отрендеренный месяц не совпадает с ожидаемым периодом

Симптом

Интерфейс показывает сетку месяца, но не тот период, который ожидали пользователи.

Вероятная причина

Видимый month, календарная система calendar или defaultMonth скроллера не согласованы.

Как проверить

  • изучите фактические month, calendar и значение, переданное в onChangePeriod

Решение

Используйте один месяц YYYY-MM-DD как источник истины и передавайте один и тот же calendar каждой части, которая его рендерит.

Собственный рендер дня теряет наглядность выбора или фокуса

Симптом

Даты по-прежнему работают логически, но пользователи не могут понять, какой день активен или выбран.

Вероятная причина

Собственный рендер отбросил важное визуальное состояние.

Как проверить

  • проверьте состояния фокуса, выбора, отключения и исключения в собственной раскладке

Решение

Сохраните визуальные признаки состояний из стандартного паттерна элемента дня.

Прокручиваемое перелистывание месяцев работает ненадёжно

Симптом

Свайп между месяцами иногда работает, но подписи периода или фокус ведут себя нестабильно.

Вероятная причина

Сопоставление периода в скроллере и отрендеренное содержимое месяца недостаточно плотно синхронизированы.

Как проверить

  • логируйте месяц, переданный в onChangePeriod, во время перелистывания

Решение

Выводите подписи из месяца, который сообщает onChangePeriod, а не вычисляйте его по индексу скроллера.