Поповеры с формами

Tippy.js — легковесная библиотека для создания интерактивных всплывающих подсказок и поповеров в веб-приложениях на JavaScript. Она использует Popper.js для позиционирования, поддерживает богатую кастомизацию и динамический контент. Один из распространённых сценариев использования — включение в поповер элементов форм, таких как input, textarea, select, кнопки отправки и другие интерактивные элементы.


Создание базового поповера с формой

Для начала необходимо подключить Tippy.js и создать элемент, к которому будет привязан поповер:





Простейший поповер с формой можно создать так:

tippy('#openForm', {
  content: `
    
`, allowHTML: true, interactive: true, placement: 'right', });

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

  • allowHTML: true позволяет вставлять в поповер HTML-контент.
  • interactive: true предотвращает закрытие поповера при клике внутри него.
  • placement определяет позицию всплывающей подсказки относительно целевого элемента.

Управление событиями формы внутри поповера

Формы в поповере остаются обычными DOM-элементами, поэтому можно использовать стандартные методы для обработки событий:

document.addEventListener('submit', function(e) {
  if (e.target.id === 'popupForm') {
    e.preventDefault();
    const formData = new FormData(e.target);
    console.log('Имя:', formData.get('name'));
    console.log('Email:', formData.get('email'));
    e.target.reset();
    e.target.closest('.tippy-box')._tippy.hide(); // закрытие поповера
  }
});

Особенности работы:

  • События обрабатываются через обычный DOM, так как элементы формы полностью доступны.
  • Метод _tippy.hide() используется для закрытия поповера программно.

Динамическая генерация контента

Иногда необходимо создавать формы динамически в зависимости от состояния приложения:

tippy('#openForm', {
  content: () => {
    const container = document.createElement('div');
    container.innerHTML = `
      
`; return container; }, allowHTML: true, interactive: true, });

Использование функции в content позволяет формировать содержимое на лету, включая данные из JavaScript, состояния интерфейса или API.


Кастомизация внешнего вида

Tippy.js предоставляет мощные возможности для стилизации:

tippy('#openForm', {
  content: `
    
`, allowHTML: true, interactive: true, theme: 'light-border', animation: 'scale', duration: [300, 200], });

Настройки:

  • theme — выбор предустановленных или кастомных тем.
  • animation — тип анимации при открытии/закрытии.
  • duration — массив [время открытия, время закрытия] в миллисекундах.

Для создания собственной темы можно использовать CSS:

.tippy-box.my-custom-theme {
  background-color: #f9f9f9;
  border: 1px solid #ccc;
  padding: 10px;
  border-radius: 6px;
}

.tippy-box.my-custom-theme button {
  background-color: #007bff;
  color: #fff;
  border: none;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
}

И подключить её через theme: 'my-custom-theme'.


Управление положением и поведением

Для сложных интерфейсов важно корректно управлять расположением поповеров и их поведением при скролле:

tippy('#openForm', {
  content: '
...
', allowHTML: true, interactive: true, placement: 'bottom-start', popperOptions: { modifiers: [ { name: 'preventOverflow', options: { boundary: 'viewport', }, }, { name: 'flip', options: { fallbackPlacements: ['top', 'right'], }, }, ], }, });

Модификаторы Popper.js:

  • preventOverflow — предотвращает выход поповера за границы экрана.
  • flip — автоматически меняет позицию, если место ограничено.

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

Для работы с несколькими формами важно избегать конфликтов идентификаторов:

const buttons = document.querySelectorAll('.openForm');

buttons.forEach((btn, index) => {
  tippy(btn, {
    content: `
`, allowHTML: true, interactive: true, }); });

Каждая форма получает уникальный id, что предотвращает пересечение событий и данных между поповерами.


Взаимодействие с внешними библиотеками и фреймворками

Tippy.js отлично интегрируется с React, Vue и другими фреймворками. Для форм это важно, так как состояние компонентов можно передавать напрямую:

Пример с React:

import Tippy from '@tippyjs/react';
import 'tippy.js/dist/tippy.css';

function FormPopover() {
  return (
    
          
          
        
      }
    >
      
    
  );
}

Поповеры с формами в таких случаях становятся частью реактивного дерева компонентов, сохраняя полную совместимость с состоянием и хуками.


Советы по UX при использовании форм в поповерах

  • Сохранять фокус внутри поповера: interactive: true и управление клавишей Tab позволяют пользователю удобно работать с формой.
  • Минимизировать размер контента: поповер не должен перекрывать ключевые элементы интерфейса.
  • Динамическая валидация: поддержка JS-валидации прямо внутри поповера делает формы интерактивными и отзывчивыми.
  • Закрытие при успешной отправке: автоматически скрывать поповер после успешной отправки формы повышает UX.