Mosmox UI
Current version
GitHubnpmjs.com
Navigation & Selection

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

ВластивістьТипЗа замовчуваннямПризначення
itemsNavigationMenuItem[]—Пункти меню.
aria-labelstringPrimary navigationAccessible name елемента <nav>.
classNamestring—Додатковий CSS-клас кореневого <nav>.
separatorReactNode—Декоративний роздільник між сусідніми пунктами: текст, вертикальна лінія або іконка.
gapnumber | string3pxВідступ між пунктами. Число задається в пікселях; рядок може бути будь-яким CSS-значенням.
orientation'horizontal' | 'vertical'horizontalНапрямок меню.
variant'plain' | 'soft'plainВізуальний режим без зовнішньої рамки.
size'xs' | 'sm' | 'default' | 'lg'defaultРозмір пунктів.
collapsedbooleanfalseКомпактний режим вертикального меню: приховує текст, описи, badge та стрілки, залишаючи іконки.
defaultCollapsedbooleanfalseПочатковий компактний стан для неконтрольованого меню.
collapseBreakpointnumber—Автоматично вмикає компактний режим, коли ширина меню менша або дорівнює значенню в px.
collapsedWidthnumber | string32Ширина вертикального меню в компактному режимі.
onCollapsedChange(collapsed: boolean) => void—Викликається при автоматичній зміні компактного стану через collapseBreakpoint.
activeKeystring—Контрольований активний пункт.
defaultActiveKeystring—Початковий активний пункт.
openKeysstring[]—Контрольовані відкриті підменю.
defaultOpenKeysstring[][]Початково відкриті підменю.
onActiveChange(key: string, item: NavigationMenuItem) => void—Викликається при виборі звичайного пункту.
onOpenChange(keys: string[]) => void—Викликається при відкритті або закритті підменю.
onItemClick(key: string, item: NavigationMenuItem) => void—Загальний callback вибору звичайного пункту.
submenuBehavior'click' | 'hover'hoverСпосіб відкриття підменю: hover — наведенням, click — лише натисканням.
closeSubmenusOnMouseLeavebooleantrueЗакривати всі відкриті підменю після виходу курсора з меню.
submenuCloseDelaynumber10Затримка закриття після виходу курсора, у секундах.
collapseSubmenusbooleanfalseВбудовує підменю у вертикальний потік.
wrapbooleanfalseДозволяє перенос горизонтальних пунктів.
fullWidthbooleanfalseРозтягує контейнер на доступну ширину.
maxHeightnumber | string—Обмеження висоти з прокручуванням.

Ці властивості можна задати глобально в 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 режим.
gapnumber | string3pxГлобальний відступ між пунктами.
submenuBehavior'click' | 'hover''hover'Спосіб відкриття підменю.
closeSubmenusOnMouseLeavebooleantrueЧи запускати автоматичне закриття після виходу курсора.
submenuCloseDelaynumber10Затримка автоматичного закриття в секундах.
collapseSubmenusbooleanfalseВідображати вертикальні підменю в потоці.
ВластивістьТипПризначення
keystringУнікальний ключ.
labelReactNodeНазва пункту.
hrefstringURL для навігації.
iconReactNodeІконка зліва. У mega menu можна замінити її через image.
iconSizenumber | stringРозмір іконки в mega menu. Число задається в px; також можна передати CSS-значення. Іконка вирівнюється по верхньому краю назви.
imagestringURL зображення для елемента mega menu. Має пріоритет над icon.
imageAspectRationumber | stringСпіввідношення сторін зображення, наприклад 16 / 9 або "4 / 3".
imageShape'square' | 'circle'Форма зображення. circle примусово використовує співвідношення 1 / 1.
badgeReactNodeЛічильник або статус справа.
descriptionReactNodeДодатковий опис.
childrenNavigationMenuItem[]Підменю, максимум до третього рівня.
megaMenuNavigationMenuMegaGroup[]Розширене підменю першого рівня з колонками та групами посилань. Не підтримує третій рівень.
megaMenuFullWidthbooleanРозтягує mega menu на всю ширину меню, залишаючи його вміст по центру.
megaMenuAsideNavigationMenuMegaAsideДодає до mega menu боковий блок зліва або справа з власною шириною, кольором і React-контентом.
megaMenuFooterReactNodeДодає нижній футер mega menu з довільним React-контентом.
disabledbooleanВимикає пункт.
externalbooleanВідкриває href у новій вкладці.
onClick(item: NavigationMenuItem) => voidЛокальна дія звичайного пункту. Для пункту з підменю спочатку змінюється стан підменю.
ВластивістьТипПризначення
keystringНеобов’язковий унікальний ключ групи.
labelReactNodeЗаголовок колонки.
itemsNavigationMenuItem[]Посилання групи з підтримкою href, icon, description, badge та external.
ВластивістьТипПризначення
side'left' | 'right'Сторона бокового блоку.
widthnumber | stringШирина блоку; число задається в px.
backgroundColorstringКолір фону. За замовчуванням використовується легкий сірий токен теми.
contentReactNodeДовільний вміст блоку.

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 та доступні для типізації даних меню.