Atomico предоставляет мощные средства для управления фокусом внутри веб-компонентов, сохраняя декларативный и реактивный подход. В этой библиотеке фокус рассматривается как часть состояния компонента, позволяя создавать доступные и интерактивные интерфейсы без прямой манипуляции DOM.
useFocusХук useFocus служит для отслеживания и управления
состоянием фокуса элемента. Он возвращает объект с двумя основными
свойствами:
focused — булево значение, указывающее, находится ли
элемент в фокусе.ref — ссылку на DOM-элемент, к которому применяется
управление фокусом.Пример применения:
import { component, useFocus, html } from "atomico";
function InputField() {
const { focused, ref } = useFocus();
return html`
<input
ref=${ref}
class=${focused ? "focused" : ""}
placeholder="Введите текст"
/>
`;
}
export const inputField = component(InputField);
В этом примере класс focused автоматически применяется к
<input> при получении фокуса. Это упрощает стилизацию
и визуальные эффекты без необходимости слушать события
focus и blur.
Atomico интегрирует управление фокусом с событиями клавиатуры, что
особенно полезно для компонентов, которые требуют навигации с помощью
клавиш Tab, ArrowUp или
ArrowDown. В связке с useFocus можно
реализовать кастомное поведение при изменении фокуса:
import { component, useFocus, html } from "atomico";
function MenuItem({ label }) {
const { focused, ref } = useFocus();
const handleKeyDown = (event) => {
if (event.key === "Enter" && focused) {
console.log(`Выбран пункт: ${label}`);
}
};
return html`
<div
ref=${ref}
class=${focused ? "focused" : ""}
onkeyd own=${handleKeyDown}
tabindex="0"
>
${label}
</div>
`;
}
export const menuItem = component(MenuItem);
Ключевой момент здесь — использование атрибута
tabindex="0". Без него элемент не будет доступен для
фокусировки с клавиатуры.
Atomico позволяет отслеживать изменения фокуса через стандартные
события focus и blur, но также предоставляет
реактивный подход через хуки. Для сложных интерфейсов с множеством
элементов можно использовать централизованное управление фокусом:
import { component, useState, useFocus, html } from "atomico";
function Form() {
const [currentFocus, setCurrentFocus] = useState(null);
const fields = ["name", "email", "password"];
const focusRefs = fields.map(() => useFocus());
const handleKeyDown = (index, event) => {
if (event.key === "ArrowDown") {
const next = (index + 1) % fields.length;
focusRefs[next].ref.current.focus();
setCurrentFocus(next);
} else if (event.key === "ArrowUp") {
const prev = (index - 1 + fields.length) % fields.length;
focusRefs[prev].ref.current.focus();
setCurrentFocus(prev);
}
};
return html`
<form>
${fields.map(
(name, i) => html`
<input
ref=${focusRefs[i].ref}
class=${currentFocus === i ? "focused" : ""}
placeholder=${name}
onkeyd own=${(e) => handleKeyDown(i, e)}
/>
`
)}
</form>
`;
}
export const form = component(Form);
В этом примере реализована циклическая навигация по полям формы с
помощью стрелок, при этом useFocus позволяет отслеживать
активное состояние каждого поля.
Фокус можно задавать не только пользователем через клавиатуру, но и
программно, используя ref.current.focus(). Atomico
полностью поддерживает этот подход, сохраняя синхронизацию
состояния:
const { ref, focused } = useFocus();
const focusInput = () => {
ref.current.focus();
};
return html`
<input ref=${ref} placeholder="Автофокус"/>
<button oncl ick=${focusInput}>Сфокусировать</button>
`;
Фокусировка через метод focus() автоматически обновляет
реактивное состояние focused, что позволяет использовать
его для условного рендеринга или стилизации.
Использование focused открывает возможности для
динамического применения CSS-классов и анимаций. Пример:
input {
border: 1px solid #ccc;
transition: border-color 0.2s;
}
input.focused {
border-color: #007aff;
}
В сочетании с Atomico это позволяет создавать интерактивные и доступные компоненты без ручного управления классами через DOM.
Для сложных компонентов, таких как модальные окна или дропдауны, важно контролировать фокус внутри контейнера. Atomico поддерживает концепцию focus trap:
import { component, useFocus, html, useEffect } from "atomico";
function Modal() {
const { ref } = useFocus();
useEffect(() => {
const firstInput = ref.current.querySelector("input");
firstInput.focus();
}, []);
return html`
<div ref=${ref} class="modal">
<input placeholder="Введите имя"/>
<input placeholder="Введите email"/>
</div>
`;
}
export const modal = component(Modal);
Фокус автоматически устанавливается на первый интерактивный элемент, а последующая навигация может быть ограничена рамками модального окна, обеспечивая доступность.
Atomico обеспечивает полноценное управление фокусом через реактивные хуки, ссылочные объекты и интеграцию с событиями клавиатуры, что позволяет создавать сложные интерфейсы с минимальной логикой управления DOM. Основные принципы — декларативность, реактивность и доступность, которые делают библиотеку удобной для построения интерактивных компонентов.