Basic Dropdown
A menu button with the full keyboard model - arrows, Home/End, Escape, focus restore.
6 個のフレームワーク中級
A wide multi-column navigation panel where every link is a menuitem on one keyboard ring.
<!--
A mega menu is still a menu button: aria-haspopup="menu" and role="menu" hold,
every link is a menuitem, and the arrow-key ring is the columns flattened in
reading order. The panel is width-capped at calc(100vw-2rem) and its grid
collapses to one column below sm, so it can never escape a 320px viewport.
-->
<div class="relative inline-block">
<button type="button" aria-haspopup="menu" aria-expanded="true" aria-controls="mega-menu" class="inline-flex items-center gap-1.5 rounded-lg border border-gray-300 bg-white px-3.5 py-2 text-sm font-semibold text-gray-700 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 dark:hover:bg-gray-800 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-900">
Products
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m6 9 6 6 6-6" /></svg>
</button>
<div id="mega-menu" role="menu" aria-label="Products" class="absolute left-0 top-[calc(100%+0.5rem)] z-20 w-[min(44rem,calc(100vw-2rem))] max-w-[calc(100vw-2rem)] rounded-xl border border-gray-200 bg-white p-3 shadow-lg dark:border-gray-700 dark:bg-gray-900">
<div class="grid grid-cols-1 gap-x-3 gap-y-4 sm:grid-cols-3">
<div role="group" aria-label="Platform" class="min-w-0">
<p class="px-2 pb-1 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Platform</p>
<button type="button" role="menuitem" class="block w-full rounded-md px-2 py-1.5 text-left hover:bg-gray-100 focus-visible:bg-gray-100 focus-visible:outline-none dark:hover:bg-gray-800 dark:focus-visible:bg-gray-800">
<span class="block truncate text-sm font-medium text-gray-900 dark:text-gray-100">Automation</span>
<span class="block truncate text-xs text-gray-500 dark:text-gray-400">Rules and triggers</span>
</button>
<button type="button" role="menuitem" class="block w-full rounded-md px-2 py-1.5 text-left hover:bg-gray-100 focus-visible:bg-gray-100 focus-visible:outline-none dark:hover:bg-gray-800 dark:focus-visible:bg-gray-800">
<span class="block truncate text-sm font-medium text-gray-900 dark:text-gray-100">Analytics</span>
<span class="block truncate text-xs text-gray-500 dark:text-gray-400">Dashboards and reports</span>
</button>
</div>
<div role="group" aria-label="Solutions" class="min-w-0">
<p class="px-2 pb-1 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Solutions</p>
<button type="button" role="menuitem" class="block w-full rounded-md px-2 py-1.5 text-left hover:bg-gray-100 focus-visible:bg-gray-100 focus-visible:outline-none dark:hover:bg-gray-800 dark:focus-visible:bg-gray-800">
<span class="block truncate text-sm font-medium text-gray-900 dark:text-gray-100">Sales</span>
<span class="block truncate text-xs text-gray-500 dark:text-gray-400">Pipeline and deals</span>
</button>
<button type="button" role="menuitem" class="block w-full rounded-md px-2 py-1.5 text-left hover:bg-gray-100 focus-visible:bg-gray-100 focus-visible:outline-none dark:hover:bg-gray-800 dark:focus-visible:bg-gray-800">
<span class="block truncate text-sm font-medium text-gray-900 dark:text-gray-100">Support</span>
<span class="block truncate text-xs text-gray-500 dark:text-gray-400">Tickets and inbox</span>
</button>
</div>
<div role="group" aria-label="Developers" class="min-w-0">
<p class="px-2 pb-1 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Developers</p>
<button type="button" role="menuitem" class="block w-full rounded-md px-2 py-1.5 text-left hover:bg-gray-100 focus-visible:bg-gray-100 focus-visible:outline-none dark:hover:bg-gray-800 dark:focus-visible:bg-gray-800">
<span class="block truncate text-sm font-medium text-gray-900 dark:text-gray-100">API</span>
<span class="block truncate text-xs text-gray-500 dark:text-gray-400">REST and webhooks</span>
</button>
<button type="button" role="menuitem" class="block w-full rounded-md px-2 py-1.5 text-left hover:bg-gray-100 focus-visible:bg-gray-100 focus-visible:outline-none dark:hover:bg-gray-800 dark:focus-visible:bg-gray-800">
<span class="block truncate text-sm font-medium text-gray-900 dark:text-gray-100">SDKs</span>
<span class="block truncate text-xs text-gray-500 dark:text-gray-400">Typed clients</span>
</button>
</div>
</div>
</div>
</div>| Prop | 型 | デフォルト | 説明 |
|---|---|---|---|
label必須 | string | - | 読み込み中に読み上げられるアクセシブルなラベル。 |
columns必須 | MegaColumn[] | - | レンダリングする項目の配列。 |
onSelect | (id: string) => void | - | ユーザーが選択したメニュー項目を引数に呼ばれます。 |
A mega menu is still a menu button, not a special case: `aria-haspopup="menu"` and `role="menu"` hold, and the arrow-key ring is the columns flattened in reading order, so Down walks column one top-to-bottom then jumps to the top of column two. Columns organise the eye; they never partition the keyboard. Each column is a `role="group"` with its own label. The panel is capped at `w-[min(44rem,calc(100vw-2rem))]` and its grid collapses to one column below `sm`, so it can never escape a 320px viewport.