コンポーネント

ナビゲーションメニュー

ウェブサイトをナビゲートするためのリンクのコレクション。

import React from 'react';
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import classNames from 'classnames';
import { CaretDownIcon } from '@radix-ui/react-icons';
import './styles.css';
const NavigationMenuDemo = () => {
return (
<NavigationMenu.Root className="NavigationMenuRoot">
<NavigationMenu.List className="NavigationMenuList">
<NavigationMenu.Item>
<NavigationMenu.Trigger className="NavigationMenuTrigger">
Learn <CaretDownIcon className="CaretDown" aria-hidden />
</NavigationMenu.Trigger>
<NavigationMenu.Content className="NavigationMenuContent">
<ul className="List one">
<li style={{ gridRow: 'span 3' }}>
<NavigationMenu.Link asChild>
<a className="Callout" href="/">
<svg aria-hidden width="38" height="38" viewBox="0 0 25 25" fill="white">
<path d="M12 25C7.58173 25 4 21.4183 4 17C4 12.5817 7.58173 9 12 9V25Z"></path>
<path d="M12 0H4V8H12V0Z"></path>
<path d="M17 8C19.2091 8 21 6.20914 21 4C21 1.79086 19.2091 0 17 0C14.7909 0 13 1.79086 13 4C13 6.20914 14.7909 8 17 8Z"></path>
</svg>
<div className="CalloutHeading">Radix Primitives</div>
<p className="CalloutText">Unstyled, accessible components for React.</p>
</a>
</NavigationMenu.Link>
</li>
<ListItem href="https://stitches.dev/" title="Stitches">
CSS-in-JS with best-in-class developer experience.
</ListItem>
<ListItem href="/colors" title="Colors">
Beautiful, thought-out palettes with auto dark mode.
</ListItem>
<ListItem href="https://icons.radix-ui.com/" title="Icons">
A crisp set of 15x15 icons, balanced and consistent.
</ListItem>
</ul>
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Trigger className="NavigationMenuTrigger">
Overview <CaretDownIcon className="CaretDown" aria-hidden />
</NavigationMenu.Trigger>
<NavigationMenu.Content className="NavigationMenuContent">
<ul className="List two">
<ListItem title="Introduction" href="/primitives/docs/overview/introduction">
Build high-quality, accessible design systems and web apps.
</ListItem>
<ListItem title="Getting started" href="/primitives/docs/overview/getting-started">
A quick tutorial to get you up and running with Radix Primitives.
</ListItem>
<ListItem title="Styling" href="/primitives/docs/guides/styling">
Unstyled and compatible with any styling solution.
</ListItem>
<ListItem title="Animation" href="/primitives/docs/guides/animation">
Use CSS keyframes or any animation library of your choice.
</ListItem>
<ListItem title="Accessibility" href="/primitives/docs/overview/accessibility">
Tested in a range of browsers and assistive technologies.
</ListItem>
<ListItem title="Releases" href="/primitives/docs/overview/releases">
Radix Primitives releases and their changelogs.
</ListItem>
</ul>
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Link className="NavigationMenuLink" href="https://github.com/radix-ui">
Github
</NavigationMenu.Link>
</NavigationMenu.Item>
<NavigationMenu.Indicator className="NavigationMenuIndicator">
<div className="Arrow" />
</NavigationMenu.Indicator>
</NavigationMenu.List>
<div className="ViewportPosition">
<NavigationMenu.Viewport className="NavigationMenuViewport" />
</div>
</NavigationMenu.Root>
);
};
const ListItem = React.forwardRef(({ className, children, title, ...props }, forwardedRef) => (
<li>
<NavigationMenu.Link asChild>
<a className={classNames('ListItemLink', className)} {...props} ref={forwardedRef}>
<div className="ListItemHeading">{title}</div>
<p className="ListItemText">{children}</p>
</a>
</NavigationMenu.Link>
</li>
));
export default NavigationMenuDemo;

機能

    制御可能または非制御可能です。

    管理されたタブフォーカスによる柔軟なレイアウト構造。

    サブメニューをサポートします。

    オプションのアクティブアイテムインジケーター。

    完全なキーボードナビゲーション。

    高度なアニメーションのためのCSS変数を公開します。

    カスタムタイミングをサポートします。

インストール

コマンドラインからコンポーネントをインストールします。

npm install @radix-ui/react-navigation-menu

構成

すべての部品をインポートして組み立てる。

import * as NavigationMenu from '@radix-ui/react-navigation-menu';
export default () => (
<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger />
<NavigationMenu.Content>
<NavigationMenu.Link />
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Link />
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Trigger />
<NavigationMenu.Content>
<NavigationMenu.Sub>
<NavigationMenu.List />
<NavigationMenu.Viewport />
</NavigationMenu.Sub>
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Indicator />
</NavigationMenu.List>
<NavigationMenu.Viewport />
</NavigationMenu.Root>
);

APIリファレンス

ルート

ナビゲーションメニューのすべての部品を含みます。

プロパティデフォルト値
defaultValue
文字列
デフォルト値なし
value
文字列
デフォルト値なし
onValueChange
関数
デフォルト値なし
delayDuration
数値
200
skipDelayDuration
数値
300
dir
列挙型
デフォルト値なし
orientation
列挙型
"horizontal"
データ属性
[data-orientation]"vertical" |"horizontal"

Sub (サブ)

サブメニューを示します。ネストしてサブメニューを作成する際には、ルートの代わりに使用します。

プロパティデフォルト値
defaultValue
文字列
デフォルト値なし
value
文字列
デフォルト値なし
onValueChange
関数
デフォルト値なし
orientation
列挙型
"horizontal"
データ属性
[data-orientation]"vertical" |"horizontal"

List (リスト)

最上位のメニューアイテムを含みます。

プロパティデフォルト値
asChild
ブール値
false
データ属性
[data-orientation]"vertical" |"horizontal"

Item (アイテム)

最上位のメニューアイテム。リンクまたはトリガーとコンテンツの組み合わせを含みます。

プロパティデフォルト値
asChild
ブール値
false
value
文字列
デフォルト値なし

Trigger (トリガー)

コンテンツを切り替えるボタン。

プロパティデフォルト値
asChild
ブール値
false
データ属性
[data-state]"open" |"closed"
[data-disabled]

無効化されている場合に表示されます。

Content (コンテンツ)

各トリガーに関連付けられたコンテンツを含みます。

プロパティデフォルト値
asChild
ブール値
false
onEscapeKeyDown
関数
デフォルト値なし
onPointerDownOutside
関数
デフォルト値なし
onFocusOutside
関数
デフォルト値なし
onInteractOutside
関数
デフォルト値なし
forceMount
ブール値
デフォルト値なし
データ属性
[data-state]"open" |"closed"
[data-motion]"to-start" |"to-end" |"from-start" |"from-end"
[data-orientation]"vertical" |"horizontal"

ナビゲーションリンク。

プロパティデフォルト値
asChild
ブール値
false
active (アクティブ)
ブール値
false
onSelect
関数
デフォルト値なし
データ属性
[data-active]

アクティブな場合に表示されます。

Indicator (インジケーター)

リストの下に表示されるオプションのインジケーター要素。現在アクティブなトリガーを強調表示するために使用されます。

プロパティデフォルト値
asChild
ブール値
false
forceMount
ブール値
デフォルト値なし
データ属性
[data-state]"visible" |"hidden"
[data-orientation]"vertical" |"horizontal"

Viewport (ビューポート)

アクティブなコンテンツをリストの外側に表示するために使用されるオプションのビューポート要素。

プロパティデフォルト値
asChild
ブール値
false
forceMount
ブール値
デフォルト値なし
データ属性
[data-state]"open" |"closed"
[data-orientation]"vertical" |"horizontal"
CSS変数説明
--radix-navigation-menu-viewport-width表示/非表示時のビューポートの幅。アクティブなコンテンツから計算されます。
--radix-navigation-menu-viewport-heightアクティブなコンテンツから計算された、表示/非表示時のビューポートの高さ

垂直方向

orientation プロパティを使用することで、垂直メニューを作成できます。

<NavigationMenu.Root orientation="vertical">
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item one</NavigationMenu.Trigger>
<NavigationMenu.Content>Item one content</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item two</NavigationMenu.Trigger>
<NavigationMenu.Content>Item Two content</NavigationMenu.Content>
</NavigationMenu.Item>
</NavigationMenu.List>
</NavigationMenu.Root>

フレキシブルなレイアウト

Content のレンダリング位置をより詳細に制御する必要がある場合、Viewport 部分を使用します。これは、デザインで調整されたDOM構造が必要な場合、または高度なアニメーションを実現するために柔軟性が必要な場合に役立ちます。タブフォーカスは自動的に維持されます。

<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item one</NavigationMenu.Trigger>
<NavigationMenu.Content>Item one content</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item two</NavigationMenu.Trigger>
<NavigationMenu.Content>Item two content</NavigationMenu.Content>
</NavigationMenu.Item>
</NavigationMenu.List>
{/* NavigationMenu.Content will be rendered here when active */}
<NavigationMenu.Viewport />
</NavigationMenu.Root>

インジケーター付き

オプションのIndicator 部分を使用して、現在アクティブなTrigger を強調表示できます。これは、矢印やハイライトなどのアニメーションによる視覚的な合図をViewport に合わせて提供したい場合に役立ちます。

// index.jsx
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import './styles.css';
export default () => (
<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item one</NavigationMenu.Trigger>
<NavigationMenu.Content>Item one content</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item two</NavigationMenu.Trigger>
<NavigationMenu.Content>Item two content</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Indicator className="NavigationMenuIndicator" />
</NavigationMenu.List>
<NavigationMenu.Viewport />
</NavigationMenu.Root>
);
/* styles.css */
.NavigationMenuIndicator {
background-color: grey;
}
.NavigationMenuIndicator[data-orientation='horizontal'] {
height: 3px;
transition: width, transform, 250ms ease;
}

サブメニュー付き

NavigationMenu をネストし、そのRoot の代わりにSub 部分を使用することで、サブメニューを作成できます。サブメニューはRoot ナビゲーションメニューとは異なり、常に1つのアイテムがアクティブである必要がある点でTabs と似ており、defaultValue を割り当てて設定することを必ず行ってください。

<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item one</NavigationMenu.Trigger>
<NavigationMenu.Content>Item one content</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item two</NavigationMenu.Trigger>
<NavigationMenu.Content>
<NavigationMenu.Sub defaultValue="sub1">
<NavigationMenu.List>
<NavigationMenu.Item value="sub1">
<NavigationMenu.Trigger>Sub item one</NavigationMenu.Trigger>
<NavigationMenu.Content>
Sub item one content
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item value="sub2">
<NavigationMenu.Trigger>Sub item two</NavigationMenu.Trigger>
<NavigationMenu.Content>
Sub item two content
</NavigationMenu.Content>
</NavigationMenu.Item>
</NavigationMenu.List>
</NavigationMenu.Sub>
</NavigationMenu.Content>
</NavigationMenu.Item>
</NavigationMenu.List>
</NavigationMenu.Root>

クライアントサイドルーティングを使用する場合

ルーティングパッケージによって提供されるLink コンポーネントを使用する必要がある場合は、カスタムコンポーネントを介してNavigationMenu.Link と組み合わせることをお勧めします。これにより、アクセシビリティと一貫性のあるキーボード操作が維持されます。Next.js を使用した例を以下に示します。

// index.jsx
import { usePathname } from 'next/navigation';
import NextLink from 'next/link';
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import './styles.css';
const Link = ({ href, ...props }) => {
const pathname = usePathname();
const isActive = href === pathname;
return (
<NavigationMenu.Link asChild active={isActive}>
<NextLink href={href} className="NavigationMenuLink" {...props} />
</NavigationMenu.Link>
);
};
export default () => (
<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<Link href="/">Home</Link>
</NavigationMenu.Item>
<NavigationMenu.Item>
<Link href="/about">About</Link>
</NavigationMenu.Item>
</NavigationMenu.List>
</NavigationMenu.Root>
);
/* styles.css */
.NavigationMenuLink {
text-decoration: none;
}
.NavigationMenuLink[data-active] {
text-decoration: 'underline';
}

高度なアニメーション

--radix-navigation-menu-viewport-[width|height]data-motion['from-start'|'to-start'|'from-end'|'to-end'] 属性を使用することで、Viewport のサイズとContent の位置を、入出力方向に基づいてアニメーション化できます。

これらをposition: absolute; と組み合わせることで、アイテム間を移動するときのスムーズなオーバーラップアニメーション効果を作成できます。

// index.jsx
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import './styles.css';
export default () => (
<NavigationMenu.Root>
<NavigationMenu.List>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item one</NavigationMenu.Trigger>
<NavigationMenu.Content className="NavigationMenuContent">
Item one content
</NavigationMenu.Content>
</NavigationMenu.Item>
<NavigationMenu.Item>
<NavigationMenu.Trigger>Item two</NavigationMenu.Trigger>
<NavigationMenu.Content className="NavigationMenuContent">
Item two content
</NavigationMenu.Content>
</NavigationMenu.Item>
</NavigationMenu.List>
<NavigationMenu.Viewport className="NavigationMenuViewport" />
</NavigationMenu.Root>
);
/* styles.css */
.NavigationMenuContent {
position: absolute;
top: 0;
left: 0;
animation-duration: 250ms;
animation-timing-function: ease;
}
.NavigationMenuContent[data-motion='from-start'] {
animation-name: enterFromLeft;
}
.NavigationMenuContent[data-motion='from-end'] {
animation-name: enterFromRight;
}
.NavigationMenuContent[data-motion='to-start'] {
animation-name: exitToLeft;
}
.NavigationMenuContent[data-motion='to-end'] {
animation-name: exitToRight;
}
.NavigationMenuViewport {
position: relative;
width: var(--radix-navigation-menu-viewport-width);
height: var(--radix-navigation-menu-viewport-height);
transition: width, height, 250ms ease;
}
@keyframes enterFromRight {
from {
opacity: 0;
transform: translateX(200px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes enterFromLeft {
from {
opacity: 0;
transform: translateX(-200px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes exitToRight {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(200px);
}
}
@keyframes exitToLeft {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(-200px);
}
}

アクセシビリティ

navigation ロール要件に準拠しています。

メニューバーとの違い

NavigationMenumenubar と混同しないでください。このプリミティブは、ナビゲーションリンクのセットを指す口語的な意味でmenu という名前を共有していますが、WAI-ARIA のmenu ロールは使用しません。これは、menumenubars が、デスクトップアプリケーションウィンドウで一般的に見られるネイティブオペレーティングシステムのメニューのように動作するためです。そのため、複合フォーカス管理や先頭文字ナビゲーションなどの複雑な機能を備えています。

これらの機能は、ウェブサイトのナビゲーションには不要とみなされることが多く、最悪の場合、確立されたウェブサイトのパターンに慣れているユーザーを混乱させる可能性があります。

詳細については、W3C の開閉式ナビゲーションメニューの例を参照してください。

メニュー内のすべてのナビゲーションリンクにはNavigationMenu.Link を使用する必要があります。これはメインリストだけでなく、NavigationMenu.Content を介してレンダリングされるコンテンツにも適用されます。active プロパティを使用してaria-current とアクティブスタイルを設定することもできます。サードパーティのルーティングコンポーネントを使用した使用方法の詳細については、この例を参照してください。

キーボード操作

キー説明
SpaceEnter
フォーカスがNavigationMenu.Triggerにある場合、コンテンツを開きます。
Tab
フォーカスを次のフォーカス可能な要素に移動します。
ArrowDown
horizontal であり、フォーカスが開いている
NavigationMenu.Triggerにある場合、フォーカスを
NavigationMenu.Content.
に移動します。次のNavigationMenu.Trigger または
NavigationMenu.Link.
ArrowUp
前のNavigationMenu.Trigger または
NavigationMenu.Link.
ArrowRightArrowLeft
vertical であり、フォーカスが開いている
NavigationMenu.Triggerにある場合、フォーカスをその
NavigationMenu.Content.
次の/前のNavigationMenu.TriggerまたはNavigationMenu.Link に移動します。
HomeEnd
フォーカスを最初/最後のNavigationMenu.Trigger または
NavigationMenu.Link.
Esc
開いているNavigationMenu.Content を閉じ、フォーカスをその
NavigationMenu.Trigger.