useTimeField — один из ключевых хуков библиотеки React
Aria, предназначенный для создания полностью доступных и гибко
настраиваемых полей ввода времени. Он реализует сложную логику работы с
часовыми и минутными сегментами, поддерживает клавиатурную навигацию,
управление фокусом, локализацию форматов времени и взаимодействие с
ассистивными технологиями.
В отличие от стандартного HTML-элемента
<input type="time">, хук предоставляет полный
контроль над отображением и поведением интерфейса, позволяя разработчику
создавать кастомные компоненты с сохранением доступности.
useTimeField реализует целый набор функций, необходимых
для корректного ввода времени:
Сегментированный ввод времени
Время разбивается на независимые сегменты:
Каждый сегмент может редактироваться отдельно.
Поддержка клавиатуры
Реализованы стандартные действия:
Локализация
Компонент автоматически адаптируется под региональные настройки:
Поддержка доступности
Интеграция с ARIA-атрибутами обеспечивает корректную работу со скринридерами.
useTimeField используется совместно с несколькими
дополнительными инструментами:
useTimeField — логика поля времениuseTimeFieldState из React Stately — управление
состояниемuseDateSegment — обработка отдельных сегментов
времениТипичная структура компонента выглядит следующим образом:
TimeField
├─ TimeSegment (hour)
├─ TimeSegment (minute)
├─ TimeSegment (second)
└─ TimeSegment (dayPeriod)
Каждый сегмент управляется отдельно, но синхронизирован с общим состоянием времени.
Для работы требуются следующие пакеты:
npm install @react-aria/datepicker
npm install @react-stately/datepicker
npm install @internationalized/date
Простейшая реализация поля времени:
import {useRef} from "react";
import {useTimeField} from "@react-aria/datepicker";
import {useTimeFieldState} from "@react-stately/datepicker";
import {useLocale} from "@react-aria/i18n";
import {Time} from "@internationalized/date";
function TimeField(props) {
let {locale} = useLocale();
let state = useTimeFieldState({
...props,
locale
});
let ref = useRef();
let {fieldProps} = useTimeField(props, state, ref);
return (
<div {...fieldProps} ref={ref}>
{state.segments.map((segment, i) => (
<DateSegment key={i} segment={segment} state={state} />
))}
</div>
);
}
Компонент рендерит набор сегментов времени, которые отображаются и управляются независимо.
Каждый сегмент обрабатывается хуком useDateSegment.
import {useRef} from "react";
import {useDateSegment} from "@react-aria/datepicker";
function DateSegment({segment, state}) {
let ref = useRef();
let {segmentProps} = useDateSegment(segment, state, ref);
return (
<span {...segmentProps} ref={ref}>
{segment.text}
</span>
);
}
Типы сегментов могут быть следующими:
| Тип сегмента | Описание |
|---|---|
| hour | часы |
| minute | минуты |
| second | секунды |
| dayPeriod | AM/PM |
| literal | разделители |
Сегменты literal не редактируются и служат только для
отображения.
Состояние поля управляется через useTimeFieldState.
let state = useTimeFieldState({
locale,
defaultValue: new Time(14, 30)
});
Объект Time описывает время:
new Time(hour, minute, second)
Пример:
new Time(9, 45)
<TimeField defaultValue={new Time(10, 0)} />
Компонент сам управляет состоянием.
const [time, setTime] = useState(new Time(12, 30));
<TimeField
value={time}
onCha nge={setTime}
/>
В этом случае состояние полностью контролируется React.
Можно задать минимальное и максимальное значение времени.
<TimeField
minValue={new Time(9, 0)}
maxValue={new Time(18, 0)}
/>
Если пользователь пытается ввести значение вне диапазона, оно автоматически корректируется.
Формат определяется локалью.
Например:
| Локаль | Формат |
|---|---|
| en-US | 12-часовой |
| de-DE | 24-часовой |
| fr-FR | 24-часовой |
Пример:
9:30 AM
или
21:30
Секунды добавляются через опцию granularity.
<TimeField granularity="second" />
Поддерживаемые значения:
"hour""minute""second"Пример структуры сегментов:
14 : 35 : 42
Можно задать шаг изменения значений.
<TimeField minuteStep={5} />
Теперь минуты будут изменяться с шагом 5:
00
05
10
15
Пока значение не введено, отображается placeholder.
--:--
Каждый сегмент имеет собственный placeholder:
| Сегмент | Placeholder |
|---|---|
| hour | –– |
| minute | –– |
Каждый сегмент может иметь разные стили.
Пример:
<span
{...segmentProps}
ref={ref}
className={segment.isPlaceholder ? "placeholder" : "value"}
>
{segment.text}
</span>
Дополнительные состояния сегмента:
| Свойство | Описание |
|---|---|
| isEditable | сегмент редактируемый |
| isPlaceholder | отображается placeholder |
| isFocused | сегмент в фокусе |
Фокус автоматически перемещается между сегментами.
Примеры:
| Действие | Результат |
|---|---|
| ArrowRight | следующий сегмент |
| ArrowLeft | предыдущий сегмент |
| Tab | следующий элемент формы |
useTimeField автоматически добавляет необходимые
ARIA-атрибуты:
role="group"aria-labelledbyaria-describedbyКаждый сегмент имеет роль:
spinbutton
Это позволяет скринридерам корректно объявлять изменения значений.
Можно добавить пользовательскую проверку.
<TimeField
validate={(time) => {
if (time.hour < 9) {
return "Рабочий день начинается с 9:00";
}
}}
/>
Если функция возвращает строку — поле считается невалидным.
Компонент легко интегрируется с HTML-формами.
Пример:
<form>
<TimeField name="meetingTime" />
</form>
При отправке формы значение сериализуется.
useTimeField позволяет реализовывать собственный
дизайн.
Пример интерфейса:
[ 10 ] : [ 30 ] AM
Стили могут включать:
import {useRef} from "react";
import {useTimeField} from "@react-aria/datepicker";
import {useTimeFieldState} from "@react-stately/datepicker";
import {useDateSegment} from "@react-aria/datepicker";
import {useLocale} from "@react-aria/i18n";
function TimeField(props) {
let {locale} = useLocale();
let state = useTimeFieldState({...props, locale});
let ref = useRef();
let {fieldProps} = useTimeField(props, state, ref);
return (
<div {...fieldProps} ref={ref}>
{state.segments.map((segment, i) => (
<Segment key={i} segment={segment} state={state} />
))}
</div>
);
}
function Segment({segment, state}) {
let ref = useRef();
let {segmentProps} = useDateSegment(segment, state, ref);
return (
<span {...segmentProps} ref={ref}>
{segment.text}
</span>
);
}
useTimeFieldХук применяется в интерфейсах, где требуется точный ввод времени:
В сочетании с useDateField и useDatePicker
можно реализовать сложные интерфейсы выбора даты и времени, полностью
контролируемые на уровне React и при этом соответствующие стандартам
доступности.