useCalendarCell для дат

Хук useCalendarCell предназначен для управления состоянием и поведением отдельной ячейки календаря в компонентах, построенных с помощью библиотеки React Aria. Он позволяет корректно обрабатывать фокус, выбор даты, доступность и взаимодействие с клавиатурой, соответствуя стандартам доступности (ARIA).


Основные функции

  1. Управление фокусом и выделением useCalendarCell предоставляет свойства для корректной работы с фокусом и выделением текущей даты. Это особенно важно для пользователей, которые используют клавиатуру или вспомогательные технологии.

  2. Поддержка доступности (ARIA) Хук генерирует атрибуты role, aria-selected, aria-disabled, которые необходимы для соответствия стандартам WAI-ARIA. Это позволяет экранным читалкам корректно интерпретировать календарь.

  3. Интеграция с состоянием календаря Хук использует контекст календаря, получая текущий месяц, выбранную дату и минимальные/максимальные значения. Это обеспечивает правильное поведение при навигации и выборе дат.


Импорт и базовое использование

import { useCalendarCell } from '@react-aria/calendar';
import { useLocale } from '@react-aria/i18n';
import { useCalendarState } from '@react-stately/calendar';
import { useRef } from 'react';

function CalendarCell({ date, state }) {
  const ref = useRef();
  const { cellProps, buttonProps, isSelected, isDisabled, formattedDate } = useCalendarCell(
    { date },
    state,
    ref
  );

  return (
    <td {...cellProps}>
      <button {...buttonProps} ref={ref} disabled={isDisabled}>
        {formattedDate}
      </button>
    </td>
  );
}

Ключевые моменты кода:

  • date — объект типа DateValue из @react-stately/calendar, представляющий конкретную дату.
  • state — объект состояния календаря, получаемый через useCalendarState, который хранит выбранную дату, фокус и настройки календаря.
  • ref — ссылка на DOM-элемент кнопки для корректной работы фокуса.
  • cellProps — свойства для контейнера ячейки (td), включая ARIA-атрибуты.
  • buttonProps — свойства для интерактивного элемента, обрабатывающего выбор даты.
  • isSelected — логическое значение, показывающее, выделена ли текущая дата.
  • isDisabled — логическое значение, показывающее, доступна ли дата для выбора.
  • formattedDate — локализованная строка даты для отображения.

Настройка состояния календаря

Состояние календаря создается с помощью useCalendarState, которое управляет выделением и фокусом на уровне всей сетки календаря:

import { useCalendarState } from '@react-stately/calendar';

const state = useCalendarState({
  visibleDuration: { months: 1 },
  minValue: new Date(2023, 0, 1),
  maxValue: new Date(2024, 11, 31),
  locale: 'ru-RU',
  selectionMode: 'single'
});

Параметры:

  • visibleDuration — период отображения календаря (месяц, год).
  • minValue и maxValue — ограничения на выбор даты.
  • locale — локализация для форматирования дат.
  • selectionMode — режим выбора (single, multiple, range).

Навигация и взаимодействие с клавиатурой

useCalendarCell автоматически обрабатывает навигацию с клавиатуры:

  • Стрелки влево/вправо — перемещение между днями.
  • Стрелки вверх/вниз — перемещение на неделю вверх/вниз.
  • Enter / Space — выбор даты.
  • Home / End — переход к первому или последнему дню месяца.
  • PageUp / PageDown — переход между месяцами или годами, в зависимости от конфигурации календаря.

Динамическая доступность и выделение

Хук позволяет динамически контролировать доступность ячеек:

const isDisabled = state.isDateUnavailable(date);
const isSelected = state.isSelected(date);
  • isDisabled возвращает true, если дата выходит за пределы minValue/maxValue или заблокирована другими условиями.
  • isSelected проверяет, выбрана ли дата в текущем состоянии календаря.

Локализация и форматирование

Для корректного отображения дат используется useLocale:

import { useLocale } from '@react-aria/i18n';

const { locale, timeZone } = useLocale();
const formattedDate = state.formatDate(date, { weekday: 'short', day: 'numeric' });

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


Советы по оптимизации

  • Использовать React.memo для ячеек — предотвращает лишние ререндеры при изменении состояния других ячеек.
  • Группировать рендеринг по неделям — улучшает производительность при больших календарях.
  • Проверять isDisabled и isSelected на уровне состояния — снижает нагрузку на DOM.
  • Использовать семантическую разметку <table> — совместимость с экранными читалками.

Взаимодействие с кастомными компонентами

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

<MyCustomButton {...buttonProps} ref={ref} disabled={isDisabled}>
  {formattedDate}
</MyCustomButton>

Важно, чтобы кастомный компонент поддерживал передачу ref и корректно обрабатывал disabled.


Итоговое применение

useCalendarCell обеспечивает:

  • Полную совместимость с ARIA для экранных читалок.
  • Корректную обработку фокуса и навигации клавиатурой.
  • Связь состояния календаря с отображением ячеек.
  • Возможность локализации и форматирования дат.
  • Гибкость при интеграции с кастомными компонентами интерфейса.

Его использование является стандартом для создания доступных и функциональных календарей в React-приложениях.