Библиотека ally.js предоставляет средства для
управления доступностью и интерактивностью элементов интерфейса, включая
динамическое управление видимостью панелей. Видимость панели
определяется не только через CSS-свойство display, но и
через атрибуты доступности (aria-hidden,
aria-expanded) и фокусируемость дочерних элементов.
Ключевые принципы:
При управлении панелями используются следующие атрибуты:
aria-hidden="true" – скрывает содержимое для технологий
доступности.aria-hidden="false" – делает содержимое видимым для
ассистивных технологий.aria-expanded – используется для кнопок, управляющих
видимостью панелей, указывая текущее состояние (true или
false).Правильная установка этих атрибутов критична для корректной работы библиотек типа ally.js, которые отслеживают состояние доступности элементов.
Пример синхронизации состояния панели и кнопки:
const toggleButton = document.getElementById('toggle-panel');
const panel = document.getElementById('panel');
toggleButton.addEventListener('click', () => {
const isExpanded = toggleButton.getAttribute('aria-expanded') === 'true';
toggleButton.setAttribute('aria-expanded', String(!isExpanded));
panel.setAttribute('aria-hidden', String(isExpanded));
});
Одной из главных задач при скрытии панели является управление фокусом. ally.js предоставляет методы для определения, какие элементы могут быть фокусируемыми, и блокирует их при скрытии панели.
Пример блокировки элементов внутри панели:
import * as ally from 'ally.js';
function hidePanel(panel) {
panel.setAttribute('aria-hidden', 'true');
const focusableElements = ally.query.tabsequence({ context: panel });
focusableElements.forEach(el => el.tabIndex = -1);
}
function showPanel(panel) {
panel.setAttribute('aria-hidden', 'false');
const focusableElements = ally.query.tabsequence({ context: panel });
focusableElements.forEach(el => el.tabIndex = 0);
}
Метод ally.query.tabsequence возвращает все элементы,
доступные для навигации с клавиатуры в пределах указанного контейнера.
Изменение tabIndex предотвращает попадание фокуса на
скрытые элементы.
Для модальных панелей важно удерживать фокус внутри видимой панели и блокировать фоновые элементы. ally.js предлагает focus trap:
const modal = document.getElementById('modal');
const trap = ally.maintain.focus({
context: modal,
ignoreByFocusDisabled: true
});
// Открытие модального окна
modal.setAttribute('aria-hidden', 'false');
// Закрытие модального окна
modal.setAttribute('aria-hidden', 'true');
trap.disengage();
Focus trap автоматически удерживает фокус внутри панели, предотвращая случайный переход на фоновые элементы.
Если панель создается динамически через JavaScript, необходимо повторно инициализировать ally.js для контроля фокуса и доступности. Это достигается с помощью методов:
ally.query.tabsequence – для пересчета фокусируемых
элементов.ally.maintain.disabled – для временного отключения
элементов вне активной панели.ally.maintain.tabfocus – для фиксации фокуса на
активной панели.Пример интеграции с динамически создаваемой панелью:
function createPanel() {
const panel = document.createElement('div');
panel.id = 'dynamic-panel';
panel.innerHTML = '<button>Закрыть</button><input type="text">';
panel.setAttribute('aria-hidden', 'true');
document.body.appendChild(panel);
const focusTrap = ally.maintain.focus({ context: panel });
panel.querySelector('button').addEventListener('click', () => {
panel.setAttribute('aria-hidden', 'true');
focusTrap.disengage();
});
return panel;
}
При управлении видимостью панелей важно:
ally.query.tabsequence при массовых изменениях DOM.aria-hidden и tabIndex
атомарно, чтобы избежать расхождения видимости и фокусируемости.Для плавного появления и скрытия панелей можно комбинировать ally.js
с CSS-анимациями. Важно задерживать изменение aria-hidden
до конца анимации или использовать transitionend:
panel.classList.add('visible');
panel.addEventListener('transitionend', () => {
panel.setAttribute('aria-hidden', 'false');
});
Это предотвращает преждевременное попадание фокуса на элементы, визуально ещё скрытые.
query и maintain.Эти подходы обеспечивают корректное взаимодействие пользователей с интерфейсом и соблюдают требования доступности по стандарту WCAG.