Navigation Menu
SEO-friendly навігація застосунку з горизонтальним, вертикальним, вкладеним і mega menu режимами.
NavigationMenu призначений для переходу між розділами сайту або застосунку. На відміну від Menu, він моделює навігацію зі станом активного маршруту, а не список команд.
Компонент рендерить пункти як HTML-посилання <a>. Це зберігає стандартну поведінку браузера, підтримує відкриття посилання в новій вкладці та дає пошуковим системам реальні URL. Для пунктів із підменю клік перехоплюється лише для відкриття або закриття підменю; для звичайного пункту з href виконується навігація.
Основні можливості
- горизонтальна або вертикальна орієнтація;
- розміри
xs,sm,defaultіlg; - активний пункт і відкриті підменю в контрольованому або неконтрольованому режимі;
- підменю до трьох рівнів із відкриттям через hover або click;
- автоматичне закриття підменю після виходу курсора та закриття по кліку поза меню;
- mega menu першого рівня з групами, колонками, описами, іконками, зображеннями, aside-блоком і footer;
- вертикальний collapsed icon rail із довільною шириною та стандартним
Tooltipдля прихованих назв; - SEO-friendly
href, зовнішні посилання, disabled-пункти, badge і довільні ReactNode; - перенесення горизонтальних пунктів, обмеження висоти та прокручування.
Базове використання
<NavigationMenu items={[{ key: 'home', label: 'Home', href: '/' }, { key: 'projects', label: 'Projects', href: '/projects' }, { key: 'settings', label: 'Settings', href: '/settings' }]} activeKey="projects" />Орієнтація та вигляд
orientation="horizontal" підходить для header, а orientation="vertical" — для sidebar. Меню не має зовнішньої рамки; доступні режими plain і soft, розміри xs, sm, default, lg, а також wrap, fullWidth і maxHeight.
Для вузького вертикального sidebar можна використовувати collapsed, щоб залишити тільки іконки. Якщо потрібно реагувати на фактичну ширину батьківського контейнера, задайте collapseBreakpoint у пікселях — меню автоматично перейде в компактний режим, коли ширина контейнера стане меншою або дорівнюватиме цьому значенню. collapsedWidth визначає ширину компактного icon rail і за замовчуванням становить 32px. Довгі назви пунктів у звичайному режимі обрізаються з ….
<NavigationMenu orientation="vertical" items={items} collapsed collapsedWidth={32} />
<NavigationMenu
orientation="vertical"
fullWidth
collapseBreakpoint={80}
items={items}
/>Роздільники між пунктами
Властивість separator вставляє довільний ReactNode між сусідніми пунктами. Роздільник є декоративним: він не фокусується, не реагує на hover і не є пунктом меню.
<NavigationMenu items={items} separator="/" />
<NavigationMenu items={items} separator={<span className="vertical-line" />} />
<NavigationMenu items={items} separator={<ChevronRight aria-hidden="true" size={14} />} />Відступ між пунктами
Для горизонтального меню відступ можна задати через gap. Число інтерпретується як пікселі, також можна передати будь-яке CSS-значення.
<NavigationMenu items={items} gap={16} />
<NavigationMenu items={items} gap="1rem" />Підменю
Пункт може мати children. Компонент підтримує максимум три рівні: пункт, підменю першого рівня та підменю другого рівня. Глибші children не відображаються. За замовчуванням submenuBehavior="hover" відкриває підменю наведенням. Щоб не відкривати підменю при наведенні та відкривати його лише натисканням, використовуйте submenuBehavior="click". За замовчуванням відкриті підменю закриваються після виходу курсора з меню через 10 секунд. Це можна вимкнути через closeSubmenusOnMouseLeave={false} або змінити затримку через submenuCloseDelay у секундах. collapseSubmenus показує вкладені меню у потоці вертикального меню.
<NavigationMenu
items={items}
closeSubmenusOnMouseLeave
submenuCloseDelay={3}
/>
<NavigationMenu
items={items}
closeSubmenusOnMouseLeave={false}
/>Для широкого підменю першого рівня використовуйте megaMenu. Воно відображає групи посилань у колонках; кожне посилання може мати іконку та опис. Вкладені children у пунктах mega menu навмисно не рендеряться, тому третій рівень у цьому режимі відсутній.
<NavigationMenu items={[
{
key: 'products',
label: 'Products',
href: '/products',
megaMenu: [
{
key: 'platform',
label: 'Platform',
items: [
{
key: 'analytics',
label: 'Analytics',
href: '/products/analytics',
icon: <BarChart3 size={16} />,
description: 'Understand your product metrics.',
},
],
},
{
key: 'resources',
label: 'Resources',
items: [
{ key: 'guides', label: 'Guides', href: '/guides', description: 'Practical advice for your team.' },
],
},
],
},
{ key: 'pricing', label: 'Pricing', href: '/pricing' },
]} />Щоб розтягнути mega menu на всю ширину меню, а його вміст залишити по центру, додайте megaMenuFullWidth до пункту та fullWidth до NavigationMenu:
<NavigationMenu fullWidth items={[{
key: 'products',
label: 'Products',
megaMenuFullWidth: true,
megaMenu: groups,
}]} /><NavigationMenu orientation="vertical" items={[{ key: 'workspace', label: 'Workspace', children: [{ key: 'projects', label: 'Projects', children: [{ key: 'active', label: 'Active projects' }, { key: 'archived', label: 'Archived projects' }] }, { key: 'team', label: 'Team' }] }]} />Кожен пункт рендериться як HTML-посилання <a>, що зручно для SEO та навігації. Передавайте реальний href для кожного пункту; якщо href не задано, компонент використовує # і залишає клік для керування підменю або callback. Пункти підтримують icon, badge, description, disabled, href, external і onClick. activeKey та openKeys можна використовувати як контрольовані значення, а defaultActiveKey і defaultOpenKeys — для початкового стану. Клавіатурна навігація підтримує стрілки, Home, End і Escape.
Підменю розкриваються праворуч у вертикальному режимі та вниз у горизонтальному. Компонент не виконує collision detection: якщо для підменю недостатньо місця у viewport, застосунок має самостійно забезпечити відповідний контейнер або використати власні стилі.
Коли вертикальне меню переходить у collapsed-режим, назва, description, badge та стрілка приховуються, а іконка залишається в одному вертикальному стовпці. Наведення або фокус на іконці показує стандартний компонент Tooltip зі стрілочкою та повною назвою пункту. Якщо пункт не має icon, у collapsed-режимі він не матиме видимого графічного представлення, тому для icon rail рекомендується задавати іконку кожному пункту.
Контрольований стан
Для інтеграції з router або власним state передавайте activeKey і/або openKeys разом із callback-ами:
const [activeKey, setActiveKey] = useState('dashboard');
const [openKeys, setOpenKeys] = useState<string[]>([]);
<NavigationMenu
items={items}
activeKey={activeKey}
openKeys={openKeys}
onActiveChange={(key) => setActiveKey(key)}
onOpenChange={setOpenKeys}
submenuBehavior="click"
/>Якщо activeKey або openKeys не передані, компонент керує відповідним станом самостійно через defaultActiveKey і defaultOpenKeys.
ConfigProvider
Глобальні налаштування задаються через components.navigationMenu. Значення властивості компонента мають пріоритет над ConfigProvider:
<ConfigProvider
components={{
navigationMenu: {
orientation: 'vertical',
size: 'sm',
variant: 'soft',
submenuBehavior: 'click',
closeSubmenusOnMouseLeave: true,
submenuCloseDelay: 3,
collapseSubmenus: false,
gap: 8,
},
}}
>
<NavigationMenu items={items} />
</ConfigProvider>Футер mega menu задається через megaMenuFooter. Він приймає довільний ReactNode, відображається окремим нижнім блоком під колонками та може містити текст, посилання або інші React-компоненти:
<NavigationMenu items={[{
key: 'products',
label: 'Products',
megaMenu: groups,
megaMenuFooter: (
<div className="mega-menu-footer">
<span>Need help choosing a plan?</span>
<a href="/contact">Talk to our team →</a>
</div>
),
}]} />API Reference
NavigationMenuProps
| Властивість | Тип | За замовчуванням | Призначення |
|---|---|---|---|
items | NavigationMenuItem[] | — | Пункти меню. |
aria-label | string | Primary navigation | Accessible name елемента <nav>. |
className | string | — | Додатковий CSS-клас кореневого <nav>. |
separator | ReactNode | — | Декоративний роздільник між сусідніми пунктами: текст, вертикальна лінія або іконка. |
gap | number | string | 3px | Відступ між пунктами. Число задається в пікселях; рядок може бути будь-яким CSS-значенням. |
orientation | 'horizontal' | 'vertical' | horizontal | Напрямок меню. |
variant | 'plain' | 'soft' | plain | Візуальний режим без зовнішньої рамки. |
size | 'xs' | 'sm' | 'default' | 'lg' | default | Розмір пунктів. |
collapsed | boolean | false | Компактний режим вертикального меню: приховує текст, описи, badge та стрілки, залишаючи іконки. |
defaultCollapsed | boolean | false | Початковий компактний стан для неконтрольованого меню. |
collapseBreakpoint | number | — | Автоматично вмикає компактний режим, коли ширина меню менша або дорівнює значенню в px. |
collapsedWidth | number | string | 32 | Ширина вертикального меню в компактному режимі. |
onCollapsedChange | (collapsed: boolean) => void | — | Викликається при автоматичній зміні компактного стану через collapseBreakpoint. |
activeKey | string | — | Контрольований активний пункт. |
defaultActiveKey | string | — | Початковий активний пункт. |
openKeys | string[] | — | Контрольовані відкриті підменю. |
defaultOpenKeys | string[] | [] | Початково відкриті підменю. |
onActiveChange | (key: string, item: NavigationMenuItem) => void | — | Викликається при виборі звичайного пункту. |
onOpenChange | (keys: string[]) => void | — | Викликається при відкритті або закритті підменю. |
onItemClick | (key: string, item: NavigationMenuItem) => void | — | Загальний callback вибору звичайного пункту. |
submenuBehavior | 'click' | 'hover' | hover | Спосіб відкриття підменю: hover — наведенням, click — лише натисканням. |
closeSubmenusOnMouseLeave | boolean | true | Закривати всі відкриті підменю після виходу курсора з меню. |
submenuCloseDelay | number | 10 | Затримка закриття після виходу курсора, у секундах. |
collapseSubmenus | boolean | false | Вбудовує підменю у вертикальний потік. |
wrap | boolean | false | Дозволяє перенос горизонтальних пунктів. |
fullWidth | boolean | false | Розтягує контейнер на доступну ширину. |
maxHeight | number | string | — | Обмеження висоти з прокручуванням. |
NavigationMenuConfig
Ці властивості можна задати глобально в ConfigProvider. Тип конфігурації підтримує orientation, size (sm, default, lg), variant, gap, submenuBehavior, closeSubmenusOnMouseLeave, submenuCloseDelay і collapseSubmenus. Компонент додатково підтримує xs, collapsed, defaultCollapsed, collapseBreakpoint, collapsedWidth, wrap, fullWidth і maxHeight локально.
| Властивість | Тип | За замовчуванням | Призначення |
|---|---|---|---|
orientation | 'horizontal' | 'vertical' | 'horizontal' | Глобальна орієнтація. |
size | 'sm' | 'default' | 'lg' | 'default' | Глобальний розмір. |
variant | 'plain' | 'soft' | 'plain' | Глобальний hover/active режим. |
gap | number | string | 3px | Глобальний відступ між пунктами. |
submenuBehavior | 'click' | 'hover' | 'hover' | Спосіб відкриття підменю. |
closeSubmenusOnMouseLeave | boolean | true | Чи запускати автоматичне закриття після виходу курсора. |
submenuCloseDelay | number | 10 | Затримка автоматичного закриття в секундах. |
collapseSubmenus | boolean | false | Відображати вертикальні підменю в потоці. |
NavigationMenuItem
| Властивість | Тип | Призначення |
|---|---|---|
key | string | Унікальний ключ. |
label | ReactNode | Назва пункту. |
href | string | URL для навігації. |
icon | ReactNode | Іконка зліва. У mega menu можна замінити її через image. |
iconSize | number | string | Розмір іконки в mega menu. Число задається в px; також можна передати CSS-значення. Іконка вирівнюється по верхньому краю назви. |
image | string | URL зображення для елемента mega menu. Має пріоритет над icon. |
imageAspectRatio | number | string | Співвідношення сторін зображення, наприклад 16 / 9 або "4 / 3". |
imageShape | 'square' | 'circle' | Форма зображення. circle примусово використовує співвідношення 1 / 1. |
badge | ReactNode | Лічильник або статус справа. |
description | ReactNode | Додатковий опис. |
children | NavigationMenuItem[] | Підменю, максимум до третього рівня. |
megaMenu | NavigationMenuMegaGroup[] | Розширене підменю першого рівня з колонками та групами посилань. Не підтримує третій рівень. |
megaMenuFullWidth | boolean | Розтягує mega menu на всю ширину меню, залишаючи його вміст по центру. |
megaMenuAside | NavigationMenuMegaAside | Додає до mega menu боковий блок зліва або справа з власною шириною, кольором і React-контентом. |
megaMenuFooter | ReactNode | Додає нижній футер mega menu з довільним React-контентом. |
disabled | boolean | Вимикає пункт. |
external | boolean | Відкриває href у новій вкладці. |
onClick | (item: NavigationMenuItem) => void | Локальна дія звичайного пункту. Для пункту з підменю спочатку змінюється стан підменю. |
NavigationMenuMegaGroup
| Властивість | Тип | Призначення |
|---|---|---|
key | string | Необов’язковий унікальний ключ групи. |
label | ReactNode | Заголовок колонки. |
items | NavigationMenuItem[] | Посилання групи з підтримкою href, icon, description, badge та external. |
NavigationMenuMegaAside
| Властивість | Тип | Призначення |
|---|---|---|
side | 'left' | 'right' | Сторона бокового блоку. |
width | number | string | Ширина блоку; число задається в px. |
backgroundColor | string | Колір фону. За замовчуванням використовується легкий сірий токен теми. |
content | ReactNode | Довільний вміст блоку. |
Accessibility і стилізація
Кореневий елемент — <nav> із aria-label, список має роль menubar, а підменю — роль menu. Пункти залишаються клавіатурно доступними посиланнями. Стрілки ArrowRight/ArrowLeft для горизонтального меню та ArrowDown/ArrowUp для вертикального переміщують фокус; Home і End переходять до першого та останнього пункту, Escape закриває відкриті підменю. Для пунктів із підменю компонент додає aria-haspopup та aria-expanded.
Усі кольори, рамки, радіуси, типографіка та focus-стани використовують токени теми ConfigProvider. Компонент не додає зовнішній border навколо самого меню; рамки підменю та mega menu є частиною поверхні меню. Для власних стилів використовуйте className і класи mm-navigation-menu__* як внутрішні implementation hooks.
Типи NavigationMenuItem, NavigationMenuMegaGroup і NavigationMenuMegaAside експортуються з пакета UI та доступні для типізації даних меню.