Модальные окна и drawers представляют собой интерфейсные компоненты для отображения дополнительного контента поверх основной страницы. Их ключевая цель — привлечение внимания пользователя к важной информации или взаимодействию без перехода на другую страницу. В SvelteKit их реализация отличается реактивностью и высокой интеграцией с компонентной моделью.
В SvelteKit модальные окна обычно реализуются через отдельный компонент, который управляет своим состоянием видимости. Стандартная структура выглядит следующим образом:
<script lang="ts">
import { createEventDispatcher } from 'svelte';
export let isOpen: boolean = false;
const dispatch = createEventDispatcher();
function closeModal() {
isOpen = false;
dispatch('close');
}
</script>
{#if isOpen}
<div class="modal-backdrop" on:click={closeModal}></div>
<div class="modal">
<slot></slot>
<button on:click={closeModal}>Закрыть</button>
</div>
{/if}
<style>
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
}
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 2rem;
border-radius: 8px;
z-index: 1000;
}
</style>
Ключевые моменты:
slot позволяет передавать внутрь
модального окна любой контент.createEventDispatcher обеспечивает связь с родительским
компонентом, позволяя отслеживать закрытие модального окна.modal-backdrop) служит для
блокировки взаимодействия с основной страницей и обработки клика вне
модального окна.В SvelteKit UI libs чаще всего используют реактивные переменные или
сторы (writable) для управления видимостью:
<script lang="ts">
import { writable } from 'svelte/store';
import Modal from './Modal.svelte';
const isModalOpen = writable(false);
function openModal() {
isModalOpen.set(true);
}
</script>
<button on:click={openModal}>Открыть модальное окно</button>
<Modal bind:isOpen={$isModalOpen}>
<h2>Заголовок модального окна</h2>
<p>Содержимое модального окна</p>
</Modal>
Использование bind:isOpen обеспечивает двустороннюю
реактивность между компонентом и стором.
Для плавного появления и исчезновения модальных окон в SvelteKit применяются встроенные переходы:
<script lang="ts">
import { fade, scale } from 'svelte/transition';
</script>
{#if isOpen}
<div class="modal-backdrop" on:click={closeModal} transition:fade></div>
<div class="modal" transition:scale>
<slot></slot>
</div>
{/if}
fade плавно изменяет прозрачность.scale увеличивает или уменьшает компонент с эффектом
масштабирования.Drawers — это панели, которые выезжают с одной из сторон экрана, чаще всего слева или справа, и используются для навигации или дополнительных опций.
<script lang="ts">
import { writable } from 'svelte/store';
const isDrawerOpen = writable(false);
function toggleDrawer() {
isDrawerOpen.update(value => !value);
}
</script>
<button on:click={toggleDrawer}>Открыть Drawer</button>
{#if $isDrawerOpen}
<div class="drawer-backdrop" on:click={toggleDrawer}></div>
<aside class="drawer">
<slot></slot>
</aside>
{/if}
<style>
.drawer-backdrop {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.4);
z-index: 900;
}
.drawer {
position: fixed;
top: 0;
right: 0;
width: 300px;
height: 100%;
background: white;
padding: 1rem;
box-shadow: -2px 0 8px rgba(0,0,0,0.2);
z-index: 1000;
}
</style>
Особенности:
aside элемент, что
улучшает семантику.transform: translateX
для эффекта выезда.Для модальных окон и drawers важно соблюдать доступность:
aria-hidden, когда компонент закрыт.Escape для закрытия:<script lang="ts">
function handleKeydown(event: KeyboardEvent) {
if (event.key === 'Escape') closeModal();
}
</script>
<div on:keydown={handleKeydown} tabindex="0">
...
</div>
В SvelteKit есть несколько популярных UI libs, например Svelte Material UI (SMUI) или Skeleton UI, которые предоставляют готовые модальные компоненты и drawers с расширенной кастомизацией.
Пример использования SMUI Drawer:
<script lang="ts">
import { Drawer, DrawerContent } from '@smui/drawer';
let open = false;
</script>
<Drawer bind:open>
<DrawerContent>
<ul>
<li>Пункт 1</li>
<li>Пункт 2</li>
</ul>
</DrawerContent>
</Drawer>
<button on:click={() => open = !open}>Toggle Drawer</button>
bind:open обеспечивает реактивное управление
видимостью.z-index и backdrop.load или fetch при
открытии.Эффективная реализация таких сценариев в SvelteKit требует строгого контроля реактивности, правильного использования сторов и событий, а также соблюдения доступности и UX стандартов.