Мобильные тултипы

Тултип (tooltip) — это контекстная подсказка, которая появляется рядом с элементом интерфейса и содержит краткое пояснение его назначения. В настольных интерфейсах подсказки традиционно отображаются при наведении курсора мыши. В мобильной среде этот механизм отсутствует: сенсорные экраны не поддерживают состояние hover, а взаимодействие происходит через касание.

Из-за этого обычные реализации тултипов оказываются неприменимыми. Попытка использовать те же подходы приводит к проблемам доступности:

  • подсказка не появляется вообще;
  • её невозможно открыть или закрыть;
  • она недоступна для пользователей экранных считывателей;
  • фокус клавиатуры не может взаимодействовать с подсказкой.

Библиотека ally.js предоставляет набор инструментов для корректной работы с фокусом, интерактивными элементами и доступностью интерфейсов. При разработке мобильных тултипов она помогает управлять фокусом, контролировать доступность элементов и корректно обрабатывать взаимодействие без hover-событий.


Архитектура мобильного тултипа

Мобильный тултип должен строиться вокруг нескольких ключевых принципов:

  1. Активация по касанию
  2. Доступность для клавиатуры
  3. Поддержка экранных считывателей
  4. Управление фокусом
  5. Явное закрытие

Типичная структура включает:

  • элемент-триггер;
  • контейнер подсказки;
  • связь через ARIA-атрибуты.
<button id="help-button" aria-describedby="tooltip-help">
  ?
</button>

<div id="tooltip-help" role="tooltip" hidden>
  Дополнительная информация о функции
</div>

В этом примере:

  • aria-describedby связывает кнопку и подсказку;
  • role="tooltip" сообщает вспомогательным технологиям о назначении элемента;
  • атрибут hidden управляет видимостью.

Управление интерактивностью с ally.js

Важная задача — определить, может ли элемент получать фокус и участвовать во взаимодействии. Модуль ally.is.focusable позволяет определить, доступен ли элемент для фокусировки.

import ally from 'ally.js';

const tooltip = document.getElementById('tooltip-help');

if (ally.is.focusable(tooltip)) {
  console.log('Элемент может получать фокус');
}

Это особенно полезно в мобильных интерфейсах, где элементы часто динамически появляются и исчезают.


Показ тултипа при касании

Поскольку hover недоступен, подсказка активируется через событие touchstart или click.

const button = document.getElementById('help-button');
const tooltip = document.getElementById('tooltip-help');

button.addEventListener('click', () => {
  tooltip.hidden = false;
});

Однако подобная реализация не решает проблему управления фокусом. После появления подсказки фокус может оставаться на исходном элементе, что создаёт проблемы для пользователей экранных считывателей.


Управление фокусом

Модуль ally.element.focus позволяет программно перемещать фокус.

ally.element.focus(tooltip);

Пример полной логики открытия:

button.addEventListener('click', () => {
  tooltip.hidden = false;
  ally.element.focus(tooltip);
});

Такой подход делает подсказку доступной для клавиатуры и вспомогательных технологий.


Ограничение фокуса внутри подсказки

Иногда тултип содержит интерактивные элементы — ссылки или кнопки. В этом случае необходимо предотвратить случайный переход фокуса за пределы контейнера.

Модуль ally.maintain.tabFocus позволяет ограничить перемещение фокуса.

const tabFocus = ally.maintain.tabFocus({
  context: tooltip
});

После закрытия подсказки контроль фокуса должен быть отключён.

tabFocus.disengage();

Возврат фокуса

После закрытия тултипа фокус должен возвращаться к исходному элементу. Это стандартная практика доступного интерфейса.

button.focus();

Полный пример:

button.addEventListener('click', () => {
  tooltip.hidden = false;
  ally.element.focus(tooltip);
});

function closeTooltip() {
  tooltip.hidden = true;
  button.focus();
}

Закрытие тултипа

Мобильные интерфейсы требуют явных способов закрытия подсказки. Возможные механизмы:

  • повторное нажатие на кнопку;
  • нажатие вне подсказки;
  • клавиша Escape (для клавиатурных устройств).

Пример обработки Escape:

document.addEventListener('keydown', (event) => {
  if (event.key === 'Escape') {
    tooltip.hidden = true;
    button.focus();
  }
});

Обнаружение интерактивных элементов

Модуль ally.query.focusable помогает найти элементы внутри тултипа, способные получать фокус.

const focusable = ally.query.focusable({
  context: tooltip
});

Это позволяет:

  • проверять доступность содержимого;
  • автоматически устанавливать начальный фокус.

Пример:

const elements = ally.query.focusable({
  context: tooltip
});

if (elements.length) {
  ally.element.focus(elements[0]);
}

Поддержка экранных считывателей

В мобильных системах (VoiceOver, TalkBack) подсказки должны корректно объявляться.

Основные рекомендации:

  • использование role="tooltip";
  • связь с триггером через aria-describedby;
  • появление тултипа после получения фокуса;
  • отсутствие автоматического скрытия без действия пользователя.

Дополнительный атрибут:

aria-live="polite"

Он сообщает экранному считывателю о появлении нового контента.


Предотвращение фокуса на скрытых элементах

Если тултип скрыт, его элементы не должны получать фокус. Для этого используется модуль ally.element.disabled.

ally.element.disabled(tooltip);

После открытия подсказки доступность возвращается.

ally.element.disabled(tooltip, false);

Это предотвращает ситуацию, когда пользователь клавиатуры попадает в невидимый элемент.


Оптимизация для сенсорных устройств

Мобильные тултипы должны учитывать особенности сенсорных интерфейсов:

Размер области касания

Минимальная зона — около 44×44 px.

Избежание перекрытия контента

Подсказка не должна закрывать элемент управления.

Автоматическое позиционирование

Подсказка должна адаптироваться к положению на экране.


Позиционирование тултипа

На мобильных устройствах экран меньше, поэтому подсказка может выходить за границы области просмотра.

Пример простого позиционирования:

const rect = button.getBoundingClientRect();

tooltip.style.top = rect.bottom + 'px';
tooltip.style.left = rect.left + 'px';

Более сложные системы используют:

  • динамическое изменение позиции;
  • проверку границ viewport;
  • адаптацию под ориентацию экрана.

Управление фокусируемостью динамических элементов

Если тултип создаётся динамически, необходимо проверить его доступность.

if (!ally.is.focusable(tooltip)) {
  tooltip.setAttribute('tabindex', '-1');
}

Это гарантирует возможность программной фокусировки.


Типичная архитектура мобильного тултипа

Компонент обычно включает:

HTML

  • триггер;
  • контейнер подсказки.

CSS

  • позиционирование;
  • анимацию появления.

JavaScript

  • обработку касаний;
  • управление фокусом;
  • доступность.

Пример комплексной реализации

import ally from 'ally.js';

const button = document.getElementById('help-button');
const tooltip = document.getElementById('tooltip-help');

let focusTrap;

function openTooltip() {
  tooltip.hidden = false;

  focusTrap = ally.maintain.tabFocus({
    context: tooltip
  });

  ally.element.focus(tooltip);
}

function closeTooltip() {
  tooltip.hidden = true;

  if (focusTrap) {
    focusTrap.disengage();
  }

  button.focus();
}

button.addEventListener('click', () => {
  if (tooltip.hidden) {
    openTooltip();
  } else {
    closeTooltip();
  }
});

document.addEventListener('keydown', (event) => {
  if (event.key === 'Escape') {
    closeTooltip();
  }
});

Такой подход обеспечивает:

  • корректную работу на сенсорных устройствах;
  • доступность для клавиатуры;
  • поддержку экранных считывателей;
  • безопасное управление фокусом.

Распространённые ошибки

Использование hover-событий

На мобильных устройствах такие события не работают.

Автоматическое скрытие

Подсказка, исчезающая без действия пользователя, нарушает доступность.

Отсутствие связи через ARIA

Без aria-describedby экранный считыватель не сможет связать подсказку с элементом.

Невидимые элементы в таб-порядке

Скрытые тултипы иногда остаются доступными для клавиатуры.


Практика разработки мобильных тултипов

Современные интерфейсы всё чаще используют мобильные подсказки для:

  • объяснения сложных функций;
  • отображения дополнительной информации;
  • обучения пользователя интерфейсу.

Библиотека ally.js предоставляет низкоуровневые инструменты для управления фокусом и доступностью. Благодаря этому тултипы могут корректно работать в условиях сенсорного взаимодействия, поддерживать клавиатурную навигацию и обеспечивать полноценную интеграцию с вспомогательными технологиями.