SkateJS — это легковесная библиотека для создания веб-компонентов, основанных на стандартных возможностях браузера. Одной из важных задач при работе с компонентами является управление фокусом: правильная установка и отслеживание фокуса повышает доступность, удобство взаимодействия и контроль над состояниями элементов интерфейса.
Фокус в браузере относится к элементу, который готов принимать
пользовательский ввод с клавиатуры. В контексте SkateJS фокус можно
контролировать на уровне компонента через методы жизненного цикла и
свойства, такие как ref, а также через стандартные
DOM-методы focus() и blur().
Каждый компонент SkateJS может содержать shadow DOM,
что создаёт дополнительный слой изоляции. Для управления фокусом внутри
shadow DOM важно понимать концепцию delegated focus: при
использовании delegatesFocus: true в shadow root, вызов
focus() на host-компоненте передаёт фокус внутрь shadow
DOM.
import { define, Component, h } from 'skatejs';
class FocusInput extends Component {
static get props() {
return {
autofocus: Boolean
};
}
connectedCallback() {
super.connectedCallback();
if (this.autofocus) {
this.focusInput();
}
}
focusInput() {
this.shadowRoot.querySelector('input')?.focus();
}
render() {
return <input type="text" />;
}
}
define('focus-input', FocusInput);
В этом примере при установке свойства autofocus
компонент автоматически устанавливает фокус на
<input> внутри shadow DOM.
SkateJS позволяет использовать свойства компонента для динамического
контроля фокуса. Создание специализированного метода, например
focusInput(), обеспечивает удобный интерфейс для внешнего
кода.
document.activeElement внутри shadow DOM.Пример геттера для проверки фокуса:
get hasFocus() {
return this.shadowRoot.activeElement === this.shadowRoot.querySelector('input');
}
Такой подход позволяет реагировать на изменения состояния фокуса и интегрировать компонент с другими элементами интерфейса.
SkateJS поддерживает стандартные DOM-события focus и
blur, а также их делегированные версии focusin
и focusout. Для компонентов с shadow DOM события
focusin и focusout удобнее использовать, так
как они всплывают.
connectedCallback() {
super.connectedCallback();
this.addEventListener('focusin', () => {
this.setAttribute('focused', '');
});
this.addEventListener('focusout', () => {
this.removeAttribute('focused');
});
}
Использование атрибута focused позволяет менять стили
компонента через CSS без необходимости напрямую манипулировать DOM.
:host([focused]) input {
border-color: blue;
}
Для сложных компонентов важно уметь управлять последовательностью
фокуса. SkateJS не накладывает ограничений на использование
tabindex, поэтому можно реализовать кастомное
поведение:
focusNext() {
const inputs = Array.from(this.shadowRoot.querySelectorAll('input'));
const index = inputs.indexOf(this.shadowRoot.activeElement);
if (index >= 0 && index < inputs.length - 1) {
inputs[index + 1].focus();
}
}
Такой метод позволяет переключать фокус между элементами внутри компонента при нажатии клавиш или по другим событиям.
Для компонентов, которые взаимодействуют с пользователем, необходимо
учитывать ARIA-атрибуты. Атрибуты
aria-activedescendant, aria-labelledby и
role помогают экранным читалкам правильно интерпретировать
состояние фокуса.
Пример использования ARIA для кастомного элемента с фокусом:
render() {
return (
<div role="textbox" aria-label="Введите текст" tabindex="0">
<input type="text" />
</div>
);
}
Здесь tabindex="0" делает контейнер фокусируемым, а role
и aria-label обеспечивают корректное взаимодействие с ассистивными
технологиями.
Фокус в SkateJS можно синхронизировать с глобальными событиями,
такими как keydown или click. Например, при
нажатии на кнопку вне компонента можно автоматически фокусировать
внутренний input:
document.querySelector('#activate').addEventListener('click', () => {
document.querySelector('focus-input').focusInput();
});
Это обеспечивает интеграцию компонентов в сложные интерфейсы, где управление фокусом распределено между несколькими элементами.
focusInput() и геттеров состояния
фокуса позволяет компонентам быть предсказуемыми и интегрируемыми в
интерфейс.Правильное управление фокусом в SkateJS повышает качество компонентов, делает их доступными и удобными для пользователей, а также упрощает интеграцию в сложные пользовательские интерфейсы.