Правильная семантика форм является ключевым аспектом доступности
веб-приложений. В библиотеке React Aria управление
связью между элементами <label> и
<input> осуществляется через специальные хуки,
которые обеспечивают корректное взаимодействие с ассистивными
технологиями, такими как экранные читалки.
useLabelОсновной инструмент для связывания метки с полем ввода — хук
useLabel. Он генерирует необходимые
атрибуты для компонента <label>, учитывая
идентификатор поля ввода, состояние ошибки, обязательность и
подсказки.
Пример базового использования:
import {useLabel} from '@react-aria/label';
function TextInput({label, id}) {
const {labelProps, fieldProps} = useLabel({label, id});
return (
<div>
<label {...labelProps}>{label}</label>
<input {...fieldProps} id={id} />
</div>
);
}
Объяснение ключевых моментов:
labelProps — объект с атрибутами для
<label> (htmlFor, id),
которые гарантируют корректную связь.fieldProps — атрибуты для
<input>, включая aria-labelledby, если
необходимо.id — уникальный идентификатор, который
связывает поле и метку.idReact Aria позволяет автоматически генерировать идентификаторы через
useId, что удобно для динамических
форм:
import {useId} from '@react-aria/utils';
import {useLabel} from '@react-aria/label';
function EmailInput({label}) {
const id = useId();
const {labelProps, fieldProps} = useLabel({label, id});
return (
<div>
<label {...labelProps}>{label}</label>
<input type="email" {...fieldProps} id={id} />
</div>
);
}
Таким образом можно избежать ручного назначения id и
минимизировать риск коллизий.
React Aria поддерживает ассоциацию полей ввода с вспомогательными
текстами через aria-describedby. Для этого можно передать
опцию description в useLabel:
function PasswordInput({label, description}) {
const id = useId();
const {labelProps, fieldProps} = useLabel({label, id, description});
return (
<div>
<label {...labelProps}>{label}</label>
<input type="password" {...fieldProps} id={id} />
<p id={`${id}-description`}>{description}</p>
</div>
);
}
Пояснение:
description добавляется к aria-describedby
автоматически.React Aria учитывает состояния обязательности (required)
и ошибки (invalid) при связывании метки и поля:
function UsernameInput({label, isRequired, validationState}) {
const id = useId();
const {labelProps, fieldProps} = useLabel({
label,
id,
isRequired,
validationState
});
return (
<div>
<label {...labelProps}>{label}</label>
<input {...fieldProps} id={id} required={isRequired} />
</div>
);
}
Особенности:
isRequired автоматически добавляет визуальный и
семантический индикатор обязательного поля.validationState="invalid" добавляет
aria-invalid, что позволяет экранным читалкам озвучивать
ошибку.React Aria позволяет использовать <label> и
<input> с кастомными компонентами, сохраняя
доступность:
import {useLabel} from '@react-aria/label';
function CustomCheckbox({label}) {
const id = useId();
const {labelProps, fieldProps} = useLabel({label, id});
return (
<div>
<label {...labelProps}>
<input type="checkbox" {...fieldProps} id={id} />
{label}
</label>
</div>
);
}
Преимущество:
useId для всех полей формы.validationState и description для
доступности.labelProps к <label> и
fieldProps к основному интерактивному элементу.useField и useTextField расширяют
функциональность, сохраняя правильные связи.Использование хуков React Aria для связывания меток и полей ввода гарантирует соблюдение стандартов доступности, упрощает поддержку форм и снижает риск ошибок при динамических интерфейсах.