ally.js — это JavaScript-библиотека, предназначенная для улучшения доступности веб-приложений. Она фокусируется на управлении фокусом, обходе интерактивных элементов и работе с клавиатурной навигацией, что соответствует стандартам ARIA. Основная идея заключается в том, чтобы элементы интерфейса были доступными не только для мыши, но и для клавиатуры и вспомогательных технологий.
Библиотека использует прогрессивное улучшение, позволяя расширять стандартное поведение браузера без разрушения существующего интерфейса. Это достигается за счет точного контроля фокуса, автоматического определения доступных элементов и динамического изменения их состояния.
Основная функция ally.js — это управление фокусом. Методы
tabNext, tabPrevious и focusable
позволяют определить и установить фокус на интерактивные элементы:
const nextElement = ally.query.next({
context: document.body,
startElement: document.activeElement
});
if(nextElement) nextElement.focus();
context — область поиска доступных
элементов.startElement — текущий активный
элемент для расчета следующего фокуса.focusable — возвращает массив
элементов, на которые можно переместить фокус, исключая скрытые и
недоступные.Для модальных окон ally.js предоставляет метод
trapFocus, который ограничивает навигацию
только элементами внутри контейнера:
const modal = document.getElementById('modal');
const stopFocusTrap = ally.trapFocus({
context: modal
});
trapFocus автоматически отслеживает клавиши
Tab и Shift+Tab.stopFocusTrap позволяет деактивировать
ограничение после закрытия модального окна.Метод tabbable() возвращает список всех элементов, на
которые можно перейти с помощью клавиши Tab:
const tabbableElements = ally.query.tabbable({ context: modal });
display: none,
visibility: hidden или disabled.Функция is.focusable(element) проверяет, можно ли
установить фокус на конкретный элемент:
if(ally.is.focusable(button)) {
button.focus();
}
Это позволяет безопасно управлять интерактивными элементами и предотвращает ошибки при попытке фокусировки на недоступных элементах.
Ally.js автоматически учитывает ARIA-атрибуты, такие как:
aria-hidden — элементы с этим атрибутом игнорируются
при навигации.aria-disabled — предотвращает фокусировку на элементах,
которые визуально доступны, но недоступны для взаимодействия.role="dialog" и другие роли модальных компонентов —
помогают правильно ограничивать фокус.Применение этих атрибутов совместно с ally.js обеспечивает соответствие WCAG 2.1 и улучшает поддержку экранных читалок.
Метод ignore позволяет временно исключить элементы из
навигации по клавиатуре:
const stopIgnoring = ally.maintain.hidden({
context: document.body,
filter: '.sidebar'
});
stopIgnoring восстанавливает
стандартное поведение.ally.query.first({ context: modal }).focus();
ally.query.last({ context: modal }).focus();
Это упрощает реализацию навигации внутри диалогов и форм, обеспечивая удобный порядок фокусировки.
Ally.js поддерживает динамически изменяемые
интерфейсы, такие как одностраничные приложения (SPA) и
интерактивные компоненты. Методы tabbable и
focusable автоматически обновляют список элементов при
изменении DOM, что исключает необходимость ручного пересчета.
Пример использования с динамическим списком:
const listContainer = document.querySelector('.dynamic-list');
const updateFocusable = () => {
const items = ally.query.tabbable({ context: listContainer });
items.forEach(item => item.setAttribute('tabindex', '0'));
};
listContainer.addEventListener('DOMNodeInserted', updateFocusable);
Ally.js предоставляет интерфейс для кастомных фильтров элементов, позволяя расширять стандартное поведение. Можно определить собственные правила, исключающие или включающие элементы в фокусную навигацию:
const customFocusable = ally.query.focusable({
context: document.body,
filter: element => element.dataset.customFocusable === 'true'
});
filter — функция, возвращающая
true для включения элемента в список фокусируемых.trapFocus для модальных окон, всплывающих
подсказок и диалогов.is.focusable перед
программной фокусировкой.tabbable и
focusable, чтобы поддерживать актуальность списка
интерактивных элементов.