Компонент Dialog

Компонент Dialog предназначен для создания модальных окон, позволяя отображать интерактивный контент поверх основного интерфейса приложения. В SvelteKit UI он реализован с учетом реактивности Svelte и предоставляет удобные методы управления состоянием, а также встроенные анимации и доступность (accessibility).


Импорт и базовое использование

Для использования Dialog необходимо импортировать соответствующий компонент из библиотеки UI:

<script>
  import { Dialog, DialogTrigger, DialogContent, DialogTitle, DialogDescription, DialogClose } from 'sveltekit-ui';
  let open = false;
</script>

<Dialog bind:open>
  <DialogTrigger>
    <button>Открыть модальное окно</button>
  </DialogTrigger>
  
  <DialogContent>
    <DialogTitle>Заголовок окна</DialogTitle>
    <DialogDescription>Описание и дополнительная информация для пользователя.</DialogDescription>
    <button on:click={() => open = false}>Закрыть</button>
  </DialogContent>
</Dialog>

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

  • DialogTrigger — элемент, который инициирует открытие модального окна.
  • DialogContent — контейнер основного содержимого диалога.
  • DialogTitle и DialogDescription — семантические элементы для доступности.
  • DialogClose может использоваться для автоматического закрытия модального окна при клике.

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

Dialog в SvelteKit UI поддерживает реактивное управление через привязку к переменной open:

<script>
  let open = false;

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

<button on:click={toggleDialog}>Переключить диалог</button>

<Dialog bind:open>
  <DialogContent>
    <DialogTitle>Динамический диалог</DialogTitle>
    <button on:click={() => open = false}>Закрыть</button>
  </DialogContent>
</Dialog>

Привязка bind:open позволяет контролировать состояние диалога программно и синхронизировать его с другими компонентами интерфейса.


Анимации открытия и закрытия

Dialog поддерживает кастомные анимации через стандартные Svelte transitions:

<script>
  import { fly, fade } from 'svelte/transition';
</script>

<Dialog bind:open>
  <DialogContent transition:fly={{ y: -20, duration: 300 }} in:fade={{ duration: 200 }}>
    <DialogTitle>Анимированный диалог</DialogTitle>
    <DialogDescription>Содержимое плавно появляется и исчезает.</DialogDescription>
  </DialogContent>
</Dialog>

Особенности:

  • transition:fly задает движение содержимого при открытии и закрытии.
  • in:fade добавляет эффект плавного появления при монтировании.

Кнопки и действия внутри Dialog

Компонент позволяет легко добавлять действия пользователя, такие как подтверждение или отмена:

<DialogContent>
  <DialogTitle>Подтверждение действия</DialogTitle>
  <DialogDescription>Вы уверены, что хотите удалить элемент?</DialogDescription>
  <div class="dialog-actions">
    <button on:click={() => handleConfirm()}>Подтвердить</button>
    <DialogClose>
      <button>Отмена</button>
    </DialogClose>
  </div>
</DialogContent>
  • DialogClose оборачивает элементы, которые должны автоматически закрывать диалог при взаимодействии.
  • Любые кнопки, не обернутые в DialogClose, можно использовать для выполнения кастомных действий, сохраняя при этом состояние open.

Модификаторы доступности

Dialog автоматически обрабатывает фокусировку и клавиатурную навигацию, поддерживая ARIA-атрибуты:

  • aria-modal="true" — указывает, что диалог блокирует взаимодействие с основным контентом.
  • Автоматическая установка фокуса на первый интерактивный элемент при открытии.
  • Закрытие при нажатии клавиши Escape.
<Dialog bind:open>
  <DialogContent>
    <DialogTitle>Доступный диалог</DialogTitle>
    <DialogDescription>Диалог полностью соответствует стандартам WCAG.</DialogDescription>
  </DialogContent>
</Dialog>

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


Встраивание сложного контента

Dialog позволяет включать компоненты любой сложности, включая формы, таблицы и интерактивные элементы:

<DialogContent>
  <DialogTitle>Форма обратной связи</DialogTitle>
  <form on:submit|preventDefault={submitForm}>
    <input type="text" placeholder="Имя" bind:value={name} required />
    <textarea placeholder="Сообщение" bind:value={message}></textarea>
    <div class="dialog-actions">
      <button type="submit">Отправить</button>
      <DialogClose>
        <button>Закрыть</button>
      </DialogClose>
    </div>
  </form>
</DialogContent>

Преимущества:

  • Встроенные формы работают в модальном окне без дополнительной логики управления фокусом.
  • Поддержка привязки Svelte (bind:value) делает данные формы реактивными.
  • Dialog легко комбинируется с другими компонентами UI библиотеки, создавая сложные пользовательские интерфейсы.

Стилизация и темы

Dialog наследует стили библиотеки UI и может быть кастомизирован через CSS-переменные или классы:

.dialog-content {
  background-color: var(--dialog-bg, white);
  border-radius: 8px;
  padding: 1.5rem;
  max-width: 500px;
}
.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 1rem;
}
  • Поддержка тем позволяет легко интегрировать модальные окна в различные визуальные стили приложения.
  • Комбинация классов и CSS-переменных обеспечивает гибкость без необходимости модификации исходного компонента.

Поддержка вложенных Dialog

SvelteKit UI позволяет создавать вложенные модальные окна, которые могут открываться из другого диалога без потери контроля состояния:

<Dialog bind:open={parentOpen}>
  <DialogTrigger>
    <button>Открыть родительский диалог</button>
  </DialogTrigger>

  <DialogContent>
    <DialogTitle>Родительский диалог</DialogTitle>
    <DialogTrigger>
      <button>Открыть дочерний диалог</button>
    </DialogTrigger>

    <DialogContent>
      <DialogTitle>Дочерний диалог</DialogTitle>
    </DialogContent>
  </DialogContent>
</Dialog>
  • Вложенные диалоги полностью сохраняют фокус и управление клавиатурой.
  • Автоматическая изоляция взаимодействий предотвращает случайное закрытие родительского окна.

Интеграция с SvelteKit маршрутизацией

Dialog можно синхронизировать с маршрутами, сохраняя состояние при навигации:

<script>
  import { page } from '$app/stores';
  $: open = $page.url.searchParams.get('modal') === 'true';
</script>

<Dialog bind:open>
  <DialogContent>
    <DialogTitle>Диалог с маршрутизацией</DialogTitle>
  </DialogContent>
</Dialog>
  • Использование query-параметров позволяет открывать диалоги по URL без дополнительных библиотек состояния.
  • Состояние модального окна остаётся реактивным и управляемым через стандартные SvelteKit сторы.

Эта реализация компонента Dialog обеспечивает мощный инструмент для построения современных интерактивных интерфейсов в SvelteKit, объединяя удобство использования, доступность и гибкость кастомизации.