Работа с модальными окнами

В библиотеке Intro.js модальные окна являются основным визуальным инструментом для управления вниманием пользователя. Они представляют собой overlay-слой, блокирующий взаимодействие с остальной частью страницы и направляющий пользователя через последовательность шагов.

Каждый шаг тура сопровождается всплывающим блоком с пояснением, который позиционируется относительно целевого элемента. При этом создаётся затемнение (overlay), а сам элемент подсвечивается.

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

  • Overlay (фон затемнения) — блокирует остальную страницу
  • Tooltip (подсказка) — окно с текстом
  • Highlight (подсветка) — рамка вокруг элемента

Настройка поведения модальных окон

Основные параметры

Поведение модального окна регулируется через конфигурацию Intro.js:

introJs().setOptions({
  showStepNumbers: true,
  exitOnOverlayClick: false,
  exitOnEsc: true,
  overlayOpacity: 0.5,
  disableInteraction: true
}).start();

Ключевые свойства:

  • exitOnOverlayClick — разрешает или запрещает закрытие при клике на фон
  • exitOnEsc — закрытие по клавише Esc
  • overlayOpacity — прозрачность затемнения
  • disableInteraction — блокировка взаимодействия с элементами

Управление жизненным циклом модального окна

Intro.js предоставляет набор событий, позволяющих контролировать поведение модальных окон на каждом этапе.

Основные события

introJs()
  .onbeforechange(function(targetElement) {
    // перед показом шага
  })
  .onchange(function(targetElement) {
    // после показа шага
  })
  .onafterchange(function(targetElement) {
    // после завершения анимации
  })
  .onexit(function() {
    // при закрытии модального окна
  })
  .start();

Практическое применение:

  • динамическая подгрузка контента
  • изменение DOM перед показом шага
  • управление состоянием интерфейса

Кастомизация внешнего вида модальных окон

Изменение стилей tooltip

Intro.js использует стандартные CSS-классы, которые можно переопределять:

.introjs-tooltip {
  background-color: #1e1e2f;
  color: #ffffff;
  border-radius: 8px;
  font-size: 14px;
}

.introjs-overlay {
  background-color: rgba(0, 0, 0, 0.7);
}

Кастомизация кнопок

.introjs-button {
  background-color: #4CAF50;
  color: white;
  border: none;
}

.introjs-nextbutton {
  background-color: #2196F3;
}

Полностью кастомные модальные окна

Intro.js позволяет отключить стандартный интерфейс и использовать собственную разметку.

Отключение стандартных элементов

introJs().setOptions({
  showButtons: false,
  showBullets: false
});

Добавление собственного HTML

introJs().setOptions({
  steps: [
    {
      element: '#step1',
      intro: '<div class="custom-modal">Собственный контент</div>'
    }
  ]
});

Работа с динамическим контентом

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

Проблема

Если элемент появляется позже (например, после AJAX-запроса), Intro.js не сможет корректно привязать шаг.

Решение

Использование отложенного запуска:

setTimeout(() => {
  introJs().start();
}, 500);

Или ручное обновление:

introJs().refresh();

Управление позиционированием

Intro.js автоматически определяет положение модального окна относительно элемента, но это можно настроить.

steps: [
  {
    element: '#button',
    intro: 'Описание кнопки',
    position: 'right'
  }
]

Доступные позиции:

  • top
  • right
  • bottom
  • left
  • auto

Управление взаимодействием пользователя

Блокировка кликов

introJs().setOptions({
  disableInteraction: true
});

Это делает модальное окно полностью контролируемым сценарием.

Разрешение взаимодействия

introJs().setOptions({
  disableInteraction: false
});

Используется в интерактивных турах.


Модальные окна и формы

При работе с формами важно учитывать, что overlay может блокировать поля ввода.

Подход

Разрешение взаимодействия:

disableInteraction: false

Или выборочное отключение overlay:

.introjs-overlay {
  pointer-events: none;
}

Программное управление модальными окнами

Переход между шагами

introJs().goToStep(2).start();

Завершение тура

introJs().exit();

Перезапуск

introJs().start();

Асинхронные сценарии

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

Пример

introJs().onbeforechange(function(targetElement) {
  return new Promise(resolve => {
    fetch('/data')
      .then(response => response.json())
      .then(data => {
        targetElement.innerHTML = data.text;
        resolve();
      });
  });
});

Производительность и оптимизация

При большом количестве шагов и сложных DOM-структурах возможны задержки.

Рекомендации

  • минимизировать количество шагов
  • избегать тяжёлых DOM-операций внутри событий
  • использовать refresh() только при необходимости
  • избегать частых перезапусков тура

Типичные проблемы и их устранение

Модальное окно отображается не там

Причина:

  • элемент скрыт (display: none)
  • неправильный контейнер

Решение:

  • убедиться, что элемент видим
  • использовать scrollToElement: true

Overlay перекрывает нужные элементы

Решение:

.introjs-helperLayer {
  z-index: 9999;
}

Неправильное позиционирование при скролле

introJs().setOptions({
  scrollToElement: true
});

Интеграция с современными фреймворками

React

Используется через refs и lifecycle:

useEffect(() => {
  introJs().start();
}, []);

Vue

mounted() {
  introJs().start();
}

Расширенные сценарии использования

Многошаговые обучающие модальные окна

Позволяют:

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

Условное отображение шагов

steps: [
  condition && {
    element: '#feature',
    intro: 'Новая функция'
  }
].filter(Boolean)

Управление состоянием модальных окон

Для сохранения прогресса:

localStorage.setItem('intro_seen', true);

Проверка:

if (!localStorage.getItem('intro_seen')) {
  introJs().start();
}

Безопасность и UX

  • избегать чрезмерного количества шагов
  • не блокировать критические действия пользователя
  • обеспечивать явную возможность закрытия
  • учитывать доступность (keyboard navigation)

Глубокая кастомизация через API

Intro.js предоставляет доступ к внутренним объектам:

const intro = introJs();
intro._introItems; // массив шагов

Позволяет:

  • динамически изменять шаги
  • внедрять сложную логику
  • интегрироваться с состоянием приложения

Управление анимациями

Анимации можно отключить:

introJs().setOptions({
  animate: false
});

Или кастомизировать через CSS:

.introjs-tooltip {
  transition: all 0.3s ease;
}

Использование нескольких модальных окон

Intro.js по умолчанию поддерживает один активный тур, но можно управлять несколькими сценариями:

const intro1 = introJs();
const intro2 = introJs();

Контроль через условия:

if (user.isNew) {
  intro1.start();
} else {
  intro2.start();
}

Тонкости работы с overlay

Overlay — важный элемент UX:

  • создаёт фокус
  • уменьшает отвлечение
  • направляет внимание

Настройка прозрачности:

overlayOpacity: 0.7

Полное отключение:

showOverlay: false

Работа с вложенными элементами

При сложной DOM-структуре:

  • важно учитывать position: relative
  • избегать overflow: hidden у родительских контейнеров

Отладка модальных окон

Полезные методы:

introJs().onchange(el => console.log(el));

И визуальная проверка:

  • z-index
  • размеры элементов
  • доступность в DOM

Итеративная настройка UX

Практика показывает, что эффективные модальные окна:

  • короткие и понятные
  • визуально чистые
  • не перегружают информацией
  • появляются в нужный момент

Настройка Intro.js в этом контексте — это не только техническая задача, но и часть проектирования пользовательского опыта.