Навигационное меню — ключевой компонент любого веб-приложения, позволяющий пользователю перемещаться между страницами и разделами. В SvelteKit меню обычно строится с использованием компонентов и реактивных переменных для управления состоянием.
<script lang="ts">
import { page } from '$app/stores';
import { derived } from 'svelte/store';
const navItems = [
{ name: 'Главная', href: '/' },
{ name: 'О нас', href: '/about' },
{ name: 'Услуги', href: '/services' },
{ name: 'Контакты', href: '/contact' }
];
const activeRoute = derived(page, $page => $page.url.pathname);
</script>
<nav>
<ul class="nav-list">
{#each navItems as item}
<li class:active={$activeRoute === item.href}>
<a href={item.href}>{item.name}</a>
</li>
{/each}
</ul>
</nav>
<style>
.nav-list {
display: flex;
gap: 1.5rem;
list-style: none;
padding: 0;
margin: 0;
}
.nav-list li a {
text-decoration: none;
color: #333;
font-weight: 500;
}
.nav-list li.active a {
color: #0070f3;
border-bottom: 2px solid #0070f3;
}
</style>
SvelteKit интегрирует стор page для отслеживания
текущего URL. При построении меню важно динамически подсвечивать
активный пункт. Это достигается с помощью
derived store, который позволяет вычислять значение на
основе текущего состояния page.
const activeRoute = derived(page, $page => $page.url.pathname);
Каждое обновление маршрута автоматически обновляет активный пункт меню, обеспечивая корректное отображение состояния без ручного управления классами.
Массив navItems позволяет легко добавлять и удалять
ссылки, делая компонент масштабируемым:
const navItems = [
{ name: 'Главная', href: '/' },
{ name: 'Блог', href: '/blog' },
{ name: 'Контакты', href: '/contact' }
];
Использование #each гарантирует, что изменения в массиве
автоматически отразятся в интерфейсе.
{#each navItems as item}
<li class:active={$activeRoute === item.href}>
<a href={item.href}>{item.name}</a>
</li>
{/each}
Для мобильных устройств меню часто скрывается за гамбургер-иконкой. SvelteKit позволяет легко управлять состоянием открытия меню через реактивные переменные.
<script lang="ts">
let isOpen = false;
</script>
<button on:click={() => isOpen = !isOpen} class="hamburger">
☰
</button>
<ul class:open={isOpen} class="mobile-nav">
{#each navItems as item}
<li>
<a href={item.href} on:click={() => isOpen = false}>{item.name}</a>
</li>
{/each}
</ul>
<style>
.mobile-nav {
display: none;
flex-direction: column;
list-style: none;
padding: 0;
}
.mobile-nav.open {
display: flex;
}
.hamburger {
font-size: 2rem;
background: none;
border: none;
cursor: pointer;
}
</style>
Популярные Svelte UI библиотеки, такие как Svelte Material UI (SMUI) и Flowbite Svelte, предоставляют готовые компоненты навигации с анимацией и адаптивностью.
Пример с SMUI:
<script>
import { TopAppBar, TopAppBarRow, TopAppBarSection, TopAppBarTitle } from '@smui/top-app-bar';
import { Button } from '@smui/button';
const navItems = ['Главная', 'Блог', 'Контакты'];
</script>
<TopAppBar>
<TopAppBarRow>
<TopAppBarSection align="start">
<TopAppBarTitle>Мой сайт</TopAppBarTitle>
</TopAppBarSection>
<TopAppBarSection align="end">
{#each navItems as item}
<Button href={"/" + item.toLowerCase()}>{item}</Button>
{/each}
</TopAppBarSection>
</TopAppBarRow>
</TopAppBar>
Использование UI-библиотек позволяет:
Для сложных приложений меню может зависеть от авторизации пользователя или других динамических данных. Использование Svelte stores позволяет централизованно управлять доступными пунктами.
import { writable } from 'svelte/store';
export const userNav = writable([
{ name: 'Профиль', href: '/profile' },
{ name: 'Выход', href: '/logout' }
]);
Подключение к компоненту:
{#each $userNav as item}
<li>
<a href={item.href}>{item.name}</a>
</li>
{/each}
Это обеспечивает динамическое изменение меню без перезагрузки страницы.
Svelte предоставляет встроенные функции для анимации:
transition:fade и animate:flip помогают
создать плавное появление элементов меню.
<ul class="mobile-nav" transition:fade>
{#each navItems as item (item.href)}
<li>{item.name}</li>
{/each}
</ul>
Использование ключей (item.href) обеспечивает корректную
работу анимаций при изменении массива.
Для многоуровневой навигации применяются вложенные списки с управлением раскрытием:
{#each navItems as item}
<li>
<a href={item.href}>{item.name}</a>
{#if item.submenu}
<ul class="submenu">
{#each item.submenu as sub}
<li><a href={sub.href}>{sub.name}</a></li>
{/each}
</ul>
{/if}
</li>
{/each}
CSS для раскрывающихся подменю:
.submenu {
display: none;
position: absolute;
list-style: none;
padding: 0.5rem;
}
li:hover > .submenu {
display: block;
}
Такой подход делает меню структурированным и интерактивным, позволяя создавать как горизонтальные, так и вертикальные меню с подуровнями.
Хотя меню кажется простым компонентом, использование реактивных переменных, стор и интеграция с UI-библиотеками SvelteKit позволяет создавать полностью динамичные, адаптивные и интерактивные навигационные интерфейсы с минимальным количеством кода и высокой поддерживаемостью.