Архитектура фронтенда
Доступные формы: чтение кода
Доступность формы решается в разметке и обработчике submit. Читайте каждый сниппет так, как читали бы его на ревью PR, и выбирайте исправление, которое senior-инженер делает первым.
Отработайте цикл ревью: заметьте сломанную связь label, live-регион, который ничего не озвучивает, пропущенное перемещение фокуса и controlled input, теряющий имя поля, — и выберите верное исправление.
Сниппет 1 — label, связанный ни с чем
function EmailField() {
return (
<div className="field">
<label>Email</label>
<input type="email" name="email" placeholder="you@example.com" />
</div>
);
}
Screen reader озвучивает это поле как «edit text» без имени. В чём баг и как исправить?
Сниппет 2 — регион ошибки, который ничего не озвучивает
function Form() {
const [error, setError] = useState("");
return (
<form onSubmit={validate}>
<input id="zip" name="zip" aria-describedby="zip-err" />
{error && <div id="zip-err" role="alert">{error}</div>}
<button>Submit</button>
</form>
);
}
Зрячие видят ошибку; многие пользователи screen reader ничего не слышат. Почему и какое минимальное исправление?
Сниппет 3 — обработчик submit, забывший про фокус
function handleSubmit(e) {
e.preventDefault();
const invalid = fields.filter((f) => !f.valid);
invalid.forEach((f) => {
f.el.setAttribute("aria-invalid", "true");
setMessage(f.id, f.error); // пишет в постоянный live-регион
});
// ...и больше ничего
}
aria-invalid выставлен, сообщения озвучиваются, но пользователи клавиатуры говорят, что форма «ничего не делает» на неудачном submit. Чего не хватает?
Сниппет 4 — controlled input, теряющий своё имя
function NameField({ value, onChange }) {
return (
<>
<span className="lbl">Full name</span>
<input
value={value}
onChange={(e) => onChange(e.target.value)}
/>
</>
);
}
Это корректно управляемый (controlled) React-input, и всё же он проваливает доступность. В чём реальная проблема и исправление?
Любой баг доступности формы виден в разметке или обработчике submit: label должен быть связан через htmlFor/id или обёртку (placeholder или соседний span именем не являются); live-регион должен быть постоянным, чтобы изменение его текста было замечено; неудачный submit должен императивно переместить фокус на первое невалидное поле, а не просто выставить aria-invalid; и controlled-vs-uncontrolled ортогонально тому, есть ли у input accessible name. Читайте разметку, найдите сломанную связь или несдвинутый фокус и исправляйте это прежде всего.