Паттерны
Статичная сетка лет
Когда использовать:
- нужные годы помещаются на одну страницу — например, ближайшие финансовые годы или недавние модельные годы
Заметки о композиции:
- используйте
YearPickerLayout; страница начинается с года, заданного вyear - задайте
rowsиcolsтак, чтобы страница вмещала ровно нужные годы, и ограничьте их черезfromиto
Компромиссы:
- просто и стабильно
- нет перелистывания; для длинных диапазонов, например годов рождения, используйте скроллер
import { Text, YearPicker, YearPickerCell, YearPickerLayout } from '@vega-ui/react';
import { useState } from 'react';
export default function StaticYearGrid() {
const [year, setYear] = useState<string | null>('2026-01-01');
return (
<div style={{ display: 'grid', gap: 'var(--spacing-6)', justifyItems: 'start', width: '100%' }}>
<YearPicker
aria-label='Budget year'
locale='en-US'
year='2025-01-01'Постраничный диапазон лет
Когда использовать:
- диапазон лет длинный, например годы рождения, и выигрывает от постраничной прокрутки с привязкой (snap)
Заметки о композиции:
- используйте
YearPickerScroller,YearPickerScrollerContentиYearPickerScrollerLayout - держите
periodуYearPickerScrollerравнымrows × colsраскладки; оба по умолчанию равны 12 - начинайте рядом с вероятным ответом через
yearи ограничивайте диапазон черезfromиto - объясняйте границы рядом с сеткой и связывайте текст через
aria-describedby
Компромиссы:
- масштабируется на любой диапазон
- больше движущихся частей, чем у статичной сетки
import {
HelperText,
YearPicker,
YearPickerCell,
YearPickerScroller,
YearPickerScrollerContent,
YearPickerScrollerLayout,
} from '@vega-ui/react';
import { useId, useState } from 'react';
export default function PagedYearRange() {
const [birthYear, setBirthYear] = useState<string | null>(null);Собственный рендеринг сетки
Когда использовать:
- нужно изменить саму структуру строк, чего шаблон ячейки сделать не может
Заметки о композиции:
- собирайте страницы через
createYearPickerGrid, а не считайте годы вручную; передавайте тот жеcalendar, что и пикеру start— первый год страницы0, аoffset— индекс страницы- форматируйте подписи через
formatCalendarDateв этом календаре (илиIntl.DateTimeFormatдля григорианских ключей), а не из ISO-ключа - если подпись сокращена, как двузначные годы здесь, передайте полный год в
aria-label
Компромиссы:
- полный контроль над разметкой
- подписи и локаль — забота приложения; если меняется только содержимое, предпочитайте шаблон ячейки
import {
YearPicker,
YearPickerItem,
YearPickerRow,
YearPickerRowGroup,
createYearPickerGrid,
} from '@vega-ui/react';
const START = '2020-01-01';
const shortFormat = new Intl.DateTimeFormat('en-US', { year: '2-digit', timeZone: 'UTC' });
const longFormat = new Intl.DateTimeFormat('en-US', { year: 'numeric', timeZone: 'UTC' });
const rows = createYearPickerGrid({ start: START, rows: 2, cols: 5 });Шаблон ячейки
Когда использовать:
- ячейкам лет нужно дополнительное содержимое: счётчик, статус или подсказка
Заметки о композиции:
- дочерние элементы
YearPickerLayoutиYearPickerScrollerLayoutрендерятся по одному разу на каждый год внутри контекста ячейки - читайте год через
useYearPickerCellContext():{ col, date, fields, label };date— первый день года - рендерите содержимое внутри
YearPickerCell, чтобы ячейка сохраняла состояния выбора, фокуса и отключения - берите номера лет из
labelилиfields, а не из ISO-строкиdate; в негригорианских календарях они отличаются, а смена эры даёт две ячейки в одном григорианском году - ищите данные по
date— он одинаков во всех календарных системах
Компромиссы:
- сохраняет сетку, ключи и клавиатурное поведение раскладки
- насыщенные ячейки могут быть тесными в маленьких размерах
import {
useYearPickerCellContext,
YearPicker,
YearPickerCell,
YearPickerLayout,
} from '@vega-ui/react';
const reports: Record<string, number> = {
'2019-01-01': 4,
'2020-01-01': 12,
'2021-01-01': 11,
'2022-01-01': 12,Сравнение
Быстрое правило выбора
Используйте YearPicker, когда целевое значение — год или видимый диапазон лет. Используйте MonthPicker или DayPicker, когда нужен более детальный выбор.
YearPicker или MonthPicker
- Используйте
YearPickerдля лет. - Используйте
MonthPickerдля месяцев.
YearPicker или DayPicker
- Используйте
YearPicker, когда цель — выбор на уровне года. - Используйте
DayPickerдля выбора конкретной даты.
Выбирайте этот компонент, когда
- сценарию продукта нужен явный выбор года
- постраничный диапазон лет удобнее просматривать, чем вводить год вручную
Не выбирайте этот компонент, когда
- на самом деле нужен месяц или полная дата
- проще было бы переключать режимы календаря на более высоком уровне
Решение проблем
Видимый диапазон лет не совпадает с нужным периодом
Симптом
Сетка рендерится, но показанный диапазон лет — не тот, которого ожидал продукт.
Вероятная причина
Видимый year, start / offset раскладки или period скроллера рассогласованы.
Как проверить
- проверьте фактический видимый год и текущий индекс скроллера, если он есть
Исправление
Передавайте годы в формате YYYY-MM-DD, держите period равным rows × cols и позвольте YearPickerScrollerLayout самому вычислять start и offset.
Перелистывание больших диапазонов лет работает ненадёжно
Симптом
Перелистывание работает, но фокус или видимый контекст ведут себя нестабильно при смене диапазонов.
Вероятная причина
Интеграция скроллера не полностью синхронизирована с контекстом видимого года.
Как проверить
- логируйте изменения видимого года при перелистывании
- сравните их с подписями отрендеренного диапазона
Исправление
Держите period равным размеру страницы раскладки и выводите подписи диапазона из отрендеренных лет.
Собственные раскладки нарушают ощущение непрерывности календаря
Симптом
Сетка лет по-прежнему рендерится, но больше не ощущается цельным пикером.
Вероятная причина
Слишком большая часть стандартной структуры сетки заменена без сохранения подсказок о порядке лет.
Как проверить
- посмотрите на собственную раскладку глазами человека без контекста разработки
Исправление
Сохраняйте явный порядок лет и по возможности переиспользуйте сетки, сгенерированные хелперами.