В FAST Element управление фокусом строится на работе с нативными методами DOM и специальных API, предоставляемых библиотекой для упрощения взаимодействия с компонентами. Ключевым элементом является возможность контролировать фокус программно, реагировать на события фокуса и создавать доступные интерфейсы.
tabindex — основной инструмент
управления порядком фокуса. В FAST Element этот атрибут можно
динамически связывать с состоянием компонента:
import { FASTElement, html, css, attr } from "@microsoft/fast-element";
export class FocusExample extends FASTElement {
@attr tabindexValue = 0;
}
FocusExample.define({
name: "focus-example",
template: html`
<button tabindex="${x => x.tabindexValue}">Нажми меня</button>
`,
styles: css`button { padding: 8px; }`
});
Значения tabindex:
0 — элемент доступен для фокусировки через клавишу Tab
по естественному порядку.-1 — элемент не участвует в последовательности фокуса,
но может быть сфокусирован программно.FAST Element позволяет программно устанавливать фокус на элемент с
помощью стандартного DOM API focus() или через привязку
ссылок на элементы через директиву ref:
import { FASTElement, html, ref } from "@microsoft/fast-element";
export class FocusController extends FASTElement {
inputElement;
focusInput() {
this.inputElement.focus();
}
}
FocusController.define({
name: "focus-controller",
template: html`
<input ${ref("inputElement")} placeholder="Введите текст" />
<button @click="${x => x.focusInput()}">Фокус на input</button>
`
});
Использование ref позволяет сохранить ссылку на
внутренний элемент DOM и безопасно управлять его состоянием вне
жизненного цикла шаблона.
FAST Element предоставляет стандартные события
focus и
blur, которые можно обрабатывать через
шаблон или программно:
html`
<input @focus="${x => x.onFocus()}" @blur="${x => x.onBlur()}" />
`
onFocus() {
console.log("Элемент получил фокус");
}
onBlur() {
console.log("Элемент потерял фокус");
}
Для комплексных компонентов важно учитывать делегирование
событий фокуса. Например, если компонент содержит несколько
вложенных элементов, можно использовать
focusin и
focusout, которые всплывают через дерево
компонентов, в отличие от focus и blur.
Для создания доступных компонентов необходимо:
tabindex.aria-label, aria-labelledby,
aria-describedby) для элементов управления.:host(:focus-within) {
outline: 2px solid var(--accent-color);
border-radius: 4px;
}
focus-within позволяет подсветить весь компонент, когда
фокус находится внутри любого дочернего элемента, улучшая доступность
сложных виджетов.
FAST Element предоставляет методы жизненного цикла, которые полезны для корректного управления фокусом:
connectedCallback() — можно программно
установить фокус на элемент после его добавления в DOM.disconnectedCallback() — рекомендуется
очищать ссылки на элементы, чтобы избежать утечек памяти при удалении
компонента.Пример:
connectedCallback() {
super.connectedCallback();
if (this.autoFocus) {
this.shadowRoot.querySelector("input")?.focus();
}
}
Для компонентов с динамическими элементами или списками FAST Element позволяет создавать утилиты для управления фокусом:
focusFirst() {
const first = this.shadowRoot.querySelector('[tabindex]:not([disabled])');
first?.focus();
}
focusLast() {
const elements = Array.from(this.shadowRoot.querySelectorAll('[tabindex]:not([disabled])'));
elements[elements.length - 1]?.focus();
}
Tab и
Shift+Tab:handleKeyDown(event) {
if (event.key === "Tab") {
const focusable = Array.from(this.shadowRoot.querySelectorAll('[tabindex]:not([disabled])'));
const currentIndex = focusable.indexOf(this.shadowRoot.activeElement);
let nextIndex = event.shiftKey ? currentIndex - 1 : currentIndex + 1;
if (nextIndex >= focusable.length) nextIndex = 0;
if (nextIndex < 0) nextIndex = focusable.length - 1;
focusable[nextIndex]?.focus();
event.preventDefault();
}
}
Этот подход обеспечивает полное управление фокусом внутри компонента без вмешательства внешнего DOM.
В сложных приложениях фокус может управляться не только компонентами FAST, но и библиотеками маршрутизации или сторонними виджетами. В таких случаях рекомендуется:
requestAnimationFrame или setTimeout для
корректного рендеринга.Пример восстановления фокуса:
restoreFocus() {
requestAnimationFrame(() => {
this.lastFocused?.focus();
});
}
Управление фокусом в FAST Element позволяет создавать сложные,
доступные и интерактивные компоненты, полностью контролируя поведение
клавиатурного взаимодействия и визуальную подсветку состояния фокуса.
Оптимальное использование tabindex, событий фокуса и
методов жизненного цикла обеспечивает надёжное и предсказуемое поведение
интерфейсов.