ally.js — это библиотека для управления доступностью (accessibility) в веб-приложениях. Она предоставляет инструменты для работы с фокусом, навигацией с клавиатуры и обнаружением элементов, доступных для взаимодействия. В отличие от стандартных методов DOM, ally.js обеспечивает более предсказуемое и кросс-браузерное поведение.
Библиотека позволяет легко находить элементы, которые могут получать фокус. Основной метод:
ally.query.focusable({ context: document.body });
Можно фильтровать результаты по условиям доступности:
ally.query.focusable({ context: document.body, includeOnlyTabbable: true });
includeOnlyTabbable ограничивает элементы только теми,
которые участвуют в табуляции, исключая скрытые или недоступные
элементы.
Для программного управления фокусом используется метод
focus:
ally.focus(element, { preventScroll: true });
Этот метод учитывает текущие правила доступности и обеспечивает
безопасное перемещение фокуса даже в сложных интерфейсах, где
стандартный element.focus() может не работать.
ally.js позволяет определить ближайший доступный элемент для навигации с клавиатуры:
ally.nextTabbable(element);
ally.previousTabbable(element);
Эти функции возвращают следующий или предыдущий фокусируемый элемент, учитывая все правила видимости, отключения и tabIndex. Это особенно полезно при создании кастомных компонентов, таких как модальные окна или выпадающие меню.
Для управления модальными окнами важен метод
makeFocusable:
ally.maintain.tabFocus({ context: modalElement });
Для временного скрытия элементов от фокуса используется:
ally.style.focusable({ context: hiddenContainer, includeOnlyTabbable: true }).forEach(el => el.tabIndex = -1);
Эта техника позволяет динамически исключать элементы из навигации с клавиатуры без удаления их из DOM.
ally.js предоставляет инструменты для проверки того, доступен ли элемент для взаимодействия:
ally.query.tabbable({ context: document.body }).forEach(el => {
console.log(ally.is.focusable(el));
});
is.focusable(element) — возвращает true,
если элемент может быть сфокусирован.is.tabbable(element) — возвращает true,
если элемент участвует в табуляции.Это позволяет создавать сложные сценарии, где фокус должен переходить только на корректные элементы.
Фокус по селектору:
ally.query.firstTabbable({ context: document.body });
ally.query.lastTabbable({ context: document.body });
Эти методы упрощают установку фокуса на первый или последний элемент в контейнере, что особенно полезно для циклических навигаций.
Поддержка динамически добавляемых элементов: ally.js корректно обрабатывает элементы, появляющиеся после загрузки страницы, без необходимости повторного обхода DOM вручную.
Интеграция с кастомными компонентами: Методы ally.js можно комбинировать с Angular-директивами для обеспечения доступности пользовательских виджетов, например, динамических вкладок, аккордеонов или виртуальных списков.
import { Directive, ElementRef, AfterViewInit } from '@angular/core';
import ally from 'ally.js';
@Directive({
selector: '[appFocusTrap]'
})
export class FocusTrapDirective implements AfterViewInit {
constructor(private el: ElementRef) {}
ngAfterViewInit() {
ally.maintain.tabFocus({ context: this.el.nativeElement });
}
}
FocusTrapDirective ограничивает фокус внутри
контейнера.AfterViewInit гарантирует, что все
дочерние элементы уже присутствуют в DOM.Эти возможности делают ally.js мощным инструментом для создания полностью доступных интерфейсов в JavaScript и Angular-приложениях. Она обеспечивает предсказуемое поведение фокуса, упрощает навигацию и помогает соответствовать стандартам доступности без сложных ручных обходов DOM.