Atomico — это современная библиотека для создания веб-компонентов на JavaScript с реактивным подходом. Одной из ключевых задач при разработке компонентов является обеспечение доступности (Accessibility, сокращённо a11y), особенно для форм, где взаимодействие пользователя с элементами управления должно быть максимально удобным и предсказуемым.
Фокус на доступности включает поддержку экранных читалок, клавиатурной навигации и корректной семантики HTML. Atomico предоставляет инструменты для интеграции этих практик без излишней сложности.
Формы должны использовать семантически корректные элементы:
<form> для контейнера формы.<label> для описания полей ввода.<input>, <textarea>,
<select> для ввода данных.aria-* для дополнительных подсказок экранным
читалкам.Atomico позволяет работать с этими элементами внутри веб-компонентов, сохраняя реактивность и интеграцию с состоянием.
Пример базовой формы в Atomico:
import { c, useState } from "atomico";
function MyForm() {
const [name, setName] = useState("");
return c("form", {
onSubmit: (event) => {
event.preventDefault();
console.log("Submitted:", name);
}
},
c("label", { for: "name" }, "Имя"),
c("input", {
id: "name",
type: "text",
value: name,
onInput: (e) => setName(e.target.value),
required: true,
"aria-required": "true"
}),
c("button", { type: "submit" }, "Отправить")
);
}
В этом примере:
<label> с атрибутом
for, связанный с input.required и aria-required
для поддержки экранных читалок.onSubmit предотвращает стандартное поведение
браузера, сохраняя контроль над отправкой формы.Atomico позволяет синхронизировать состояние полей формы с
реактивными переменными через useState. Это даёт
возможность:
aria-invalid.aria-describedby.Пример с валидацией:
function ValidatedForm() {
const [email, setEmail] = useState("");
const [error, setError] = useState("");
function validateEmail(value) {
return /\S+@\S+\.\S+/.test(value);
}
return c("form", { onSubmit: e => e.preventDefault() },
c("label", { for: "email" }, "Email"),
c("input", {
id: "email",
type: "email",
value: email,
onInput: (e) => {
const val = e.target.value;
setEmail(val);
setError(validateEmail(val) ? "" : "Некорректный email");
},
"aria-invalid": !!error,
"aria-describedby": error ? "email-error" : undefined,
required: true
}),
error && c("span", { id: "email-error", role: "alert" }, error),
c("button", { type: "submit", disabled: !!error }, "Отправить")
);
}
Особенности:
aria-invalid информирует пользователя о неверном
вводе.aria-describedby указывает на элемент с текстом
ошибки.role="alert" обеспечивает мгновенное озвучивание ошибки
экранной читалкой.Для доступности критически важно поддерживать навигацию с клавиатуры:
tabindex обычно
не нужен для стандартных элементов, но полезен для кастомных
компонентов).onKeyDown или onKeyUp позволяют
реализовать кастомные комбинации клавиш.Пример кастомного select:
function CustomSelect({ options }) {
const [open, setOpen] = useState(false);
const [selected, setSelected] = useState(null);
return c("div", {
role: "listbox",
tabindex: 0,
"aria-expanded": open,
onKeyDown: (e) => {
if(e.key === "Enter" || e.key === " ") setOpen(!open);
},
onClick: () => setOpen(!open)
},
selected ?? "Выберите значение",
open && c("ul", {},
options.map(opt =>
c("li", {
role: "option",
"aria-selected": selected === opt,
onClick: () => setSelected(opt)
}, opt)
)
)
);
}
Здесь:
aria-selected указывает на текущий выбор для экранных
читалок.Atomico сочетает реактивность и семантическую разметку, что позволяет строить доступные формы без дублирования логики. Основные принципы:
Правильная реализация этих практик делает веб-компоненты на Atomico доступными для всех пользователей, включая людей с ограничениями.