Компонент Popover

Основная концепция Popover

Popover — это интерактивный всплывающий элемент, который появляется поверх контента и используется для отображения вспомогательной информации, подсказок, меню или действий, связанных с определённым элементом интерфейса. В контексте SvelteKit и UI-библиотек, Popover реализуется как компонент с контролируемым состоянием видимости и возможностью гибкой кастомизации.

Ключевые особенности Popover:

  • Контекстная привязка: Popover обычно привязывается к конкретному DOM-элементу (триггеру), обеспечивая корректное позиционирование.
  • Динамическая позиция: Возможность автоматической корректировки позиции в зависимости от видимой области окна.
  • Управление состоянием: Поддержка как внутреннего состояния (open/closed), так и внешнего контроля через props.
  • Анимация появления и скрытия: Возможность подключать переходы Svelte для плавного отображения.

Создание базового Popover

Простейший Popover состоит из двух частей: триггера и контента. В SvelteKit UI libs это может выглядеть следующим образом:

<script>
  import { Popover, PopoverTrigger, PopoverContent } from 'sveltekit-ui';
  let isOpen = false;
</script>

<Popover bind:open={isOpen}>
  <PopoverTrigger>
    <button>Открыть Popover</button>
  </PopoverTrigger>
  <PopoverContent>
    <p>Содержимое Popover</p>
  </PopoverContent>
</Popover>

Разбор кода:

  • <Popover> управляет состоянием видимости через привязку bind:open.
  • <PopoverTrigger> задаёт элемент, который вызывает отображение Popover при клике или наведении.
  • <PopoverContent> содержит основной контент Popover, который отображается поверх других элементов.

Позиционирование Popover

Позиция Popover может быть верхняя, нижняя, левая, правая, а также поддерживать автоматическое смещение для предотвращения выхода за границы экрана.

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

<Popover bind:open={isOpen} placement="bottom-start">
  <PopoverTrigger>
    <button>Меню действий</button>
  </PopoverTrigger>
  <PopoverContent>
    <ul>
      <li>Действие 1</li>
      <li>Действие 2</li>
      <li>Действие 3</li>
    </ul>
  </PopoverContent>
</Popover>

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

  • placement — ключевой prop, который задаёт предпочтительное положение относительно триггера. Возможные значения: top, bottom, left, right с модификаторами -start и -end.
  • Попробованные UI-библиотеки автоматически корректируют позицию при ограниченном пространстве.

Управление состоянием

Popover поддерживает два режима управления:

  1. Контролируемый режим — внешний компонент полностью управляет состоянием видимости через props:
<script>
  let open = false;

  function togglePopover() {
    open = !open;
  }
</script>

<Popover {open}>
  <PopoverTrigger>
    <button on:click={togglePopover}>Триггер</button>
  </PopoverTrigger>
  <PopoverContent>
    <p>Динамический контент</p>
  </PopoverContent>
</Popover>
  1. Неконтролируемый режим — Popover сам управляет своим состоянием, достаточно лишь обернуть контент в триггер.

Триггеры и события

Popover может открываться по разным событиям:

  • click — стандартное поведение для меню или действий.
  • hover — удобно для подсказок или справочной информации.
  • focus — полезно для элементов форм и доступности.

Пример триггера по наведению:

<Popover openOnHover>
  <PopoverTrigger>
    <button>Наведи на меня</button>
  </PopoverTrigger>
  <PopoverContent>
    <p>Подсказка при наведении</p>
  </PopoverContent>
</Popover>

Анимации и переходы

Для плавного появления Popover можно использовать встроенные transition Svelte:

<Popover bind:open={isOpen}>
  <PopoverTrigger>
    <button>Показать Popover</button>
  </PopoverTrigger>
  <PopoverContent transition:fade={{ duration: 200 }}>
    <p>Контент с анимацией</p>
  </PopoverContent>
</Popover>

Особенности анимаций:

  • fade, fly, scale и другие transitions доступны из svelte/transition.
  • Можно комбинировать несколько переходов для сложных эффектов.
  • Анимация не мешает управлению состоянием open.

Кастомизация стилей

Popover в SvelteKit UI libs обычно предоставляет возможность полного контроля стилей через props или классы. Пример кастомизации:

<Popover class="custom-popover">
  <PopoverTrigger>
    <button class="trigger-btn">Меню</button>
  </PopoverTrigger>
  <PopoverContent class="popover-content">
    <p>Настраиваемый Popover</p>
  </PopoverContent>
</Popover>

<style>
  .custom-popover {
    font-family: 'Inter', sans-serif;
  }
  .trigger-btn {
    background-color: #0055ff;
    color: white;
    border-radius: 6px;
    padding: 0.5rem 1rem;
  }
  .popover-content {
    background-color: #f9f9f9;
    border: 1px solid #ccc;
    padding: 1rem;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  }
</style>

Важные моменты кастомизации:

  • Возможность добавления классов на каждый элемент (Popover, PopoverTrigger, PopoverContent).
  • Поддержка CSS-переменных для динамического изменения цветов, размеров и теней.
  • Полная интеграция с TailwindCSS или другими утилитарными библиотеками для Svelte.

Вложенные Popover и взаимодействие с другими компонентами

Popover можно вкладывать один в другой, например, для создания многоуровневых меню:

<Popover>
  <PopoverTrigger>
    <button>Главное меню</button>
  </PopoverTrigger>
  <PopoverContent>
    <ul>
      <li>Пункт 1</li>
      <li>
        <Popover>
          <PopoverTrigger>
            <button>Подменю</button>
          </PopoverTrigger>
          <PopoverContent>
            <p>Вложенный Popover</p>
          </PopoverContent>
        </Popover>
      </li>
      <li>Пункт 3</li>
    </ul>
  </PopoverContent>
</Popover>

Рекомендации при вложении:

  • Следить за корректным позиционированием и z-index.
  • Использовать отдельные состояния для каждого Popover, чтобы избежать конфликтов при открытии/закрытии.

Доступность и ARIA

Popover должен быть доступным для клавиатурного навигации и вспомогательных технологий:

  • aria-haspopup="true" на триггере.
  • aria-expanded отражает состояние open.
  • Поддержка клавиш Escape для закрытия и Tab для навигации внутри Popover.
  • Фокус автоматически переводится на Popover при открытии, а возвращается на триггер при закрытии.

Пример с доступностью:

<Popover bind:open={isOpen}>
  <PopoverTrigger aria-haspopup="true" aria-expanded={isOpen}>
    <button>Помощь</button>
  </PopoverTrigger>
  <PopoverContent>
    <p>Доступный контент</p>
  </PopoverContent>
</Popover>

Popovers в SvelteKit UI libs представляют собой мощный инструмент для создания интерактивных и гибких интерфейсов, обеспечивая полный контроль над состоянием, стилями, анимацией и доступностью. Их универсальность позволяет использовать как для небольших подсказок, так и для сложных вложенных меню с динамическим контентом.