Foundation
PackagesUIComponents

DropdownMenu

トリガー要素をクリックするとアクションの一覧を表示するメニューコンポーネント。テーブル行アクション、ユーザーメニュー、ツールバーのオーバーフローメニュー等に使用する。

いつ使うか

  • テーブル行ごとに編集・削除などの操作メニューを提供するときに使用する
  • ヘッダーのユーザーアイコンからアカウント操作メニューを表示するときに使用する
  • ツールバーで表示しきれない操作を「その他」メニューにまとめるときに使用する

いつ使わないか

  • 選択肢の中から一つを選ぶフォーム入力には使わない。Select を使用する
  • 右クリックで表示するメニューには使わない。ContextMenu を使用する(将来実装)
  • 確認が必要な破壊的操作には、メニューから直接実行せず ConfirmDialog と組み合わせる

Usage

import { DropdownMenu } from '@bi-shop-it/ui/dropdown-menu';

// 単一グループの場合は items を直接渡せる
<DropdownMenu
  trigger={
    <IconButton aria-label="操作" icon="MoreHorizontal" variant="ghost" />
  }
  items={[
    { label: '編集', icon: 'Edit', onSelect: handleEdit },
    { label: '複製', icon: 'Copy', onSelect: handleDuplicate },
  ]}
/>;

// 複数グループに分ける場合は groups を使用する
<DropdownMenu
  trigger={
    <IconButton aria-label="操作" icon="MoreHorizontal" variant="ghost" />
  }
  groups={[
    {
      items: [
        { label: '編集', icon: 'Edit', onSelect: handleEdit },
        { label: '複製', icon: 'Copy', onSelect: handleDuplicate },
      ],
    },
    {
      items: [
        {
          label: '削除',
          icon: 'Trash2',
          variant: 'destructive',
          onSelect: handleDelete,
        },
      ],
    },
  ]}
/>;

Props

Propデフォルト説明
triggerReactNodeメニューを開くトリガー要素
itemsDropdownMenuItemDef[]メニューアイテムの配列(単一グループの場合に使用。groups と排他)
groupsDropdownMenuGroupDef[]メニューグループの配列(items と排他)。グループ間にセパレーターが自動挿入される
align'start' | 'center' | 'end''start'メニューの水平方向の配置
Propデフォルト説明
itemsDropdownMenuItemDef[]グループ内のメニューアイテム
labelstringグループの見出しラベル
Propデフォルト説明
labelstringメニューアイテムのラベル
onSelect() => void選択時のコールバック
iconIconNameアイテムの左側に表示するアイコン
variant'default' | 'destructive''default'アイテムのバリアント。destructive は赤色で表示される
disabledbooleanfalse無効状態

バリエーション

基本

テーブル行の操作メニューとして使用する基本パターン。グループを分けることで、通常操作と破壊的操作を視覚的に区別する。

<DropdownMenu
  trigger={
    <IconButton aria-label="操作" icon="MoreHorizontal" variant="ghost" />
  }
  groups={[
    {
      items: [
        { label: '編集', icon: 'Edit', onSelect: handleEdit },
        { label: '複製', icon: 'Copy', onSelect: handleDuplicate },
      ],
    },
    {
      items: [
        {
          label: '削除',
          icon: 'Trash2',
          variant: 'destructive',
          onSelect: handleDelete,
        },
      ],
    },
  ]}
/>

グループ見出し付き

label を指定すると、グループの先頭に見出しが表示される。ユーザーメニューのようにカテゴリ分けが必要な場合に使用する。

<DropdownMenu
  trigger={
    <IconButton aria-label="アカウントメニュー" icon="User" variant="outline" />
  }
  groups={[
    {
      label: 'アカウント',
      items: [
        { label: 'プロフィール', icon: 'User', onSelect: handleProfile },
        { label: '設定', icon: 'Settings', onSelect: handleSettings },
      ],
    },
    {
      items: [
        {
          label: 'ログアウト',
          icon: 'LogOut',
          variant: 'destructive',
          onSelect: handleLogout,
        },
      ],
    },
  ]}
/>

無効なアイテム

disabled: true を指定すると、アイテムが半透明になりクリックできなくなる。

<DropdownMenu
  trigger={
    <IconButton aria-label="操作" icon="MoreHorizontal" variant="ghost" />
  }
  items={[
    { label: '編集', icon: 'Edit', onSelect: handleEdit },
    {
      label: '複製',
      icon: 'Copy',
      onSelect: handleDuplicate,
      disabled: true,
    },
    { label: '共有', icon: 'Share', onSelect: handleShare },
  ]}
/>

右寄せ(テーブル行アクション)

align="end" を指定すると、メニューがトリガーの右端に揃う。テーブルの右端列に配置する場合に使用する。

<DropdownMenu
  align="end"
  trigger={
    <IconButton aria-label="操作" icon="MoreHorizontal" variant="ghost" />
  }
  groups={[
    {
      items: [
        { label: '編集', icon: 'Edit', onSelect: handleEdit },
        { label: '複製', icon: 'Copy', onSelect: handleDuplicate },
      ],
    },
    {
      items: [
        {
          label: '削除',
          icon: 'Trash2',
          variant: 'destructive',
          onSelect: handleDelete,
        },
      ],
    },
  ]}
/>

アクセシビリティ

コンポーネントが内部で処理すること

  • Radix UI の DropdownMenu プリミティブに基づき、role="menu"role="menuitem" を自動的に設定する
  • 矢印キーでメニューアイテム間を移動できる
  • Enter / Space キーでアイテムを選択できる
  • Escape キーでメニューを閉じ、トリガーにフォーカスが戻る

利用者が対応すること

  • トリガーが IconButton の場合、aria-label を必ず設定すること
  • 破壊的操作(削除など)は variant: 'destructive' を指定し、視覚的に区別すること
  • 削除などの取り消せない操作は、onSelect 内で ConfirmDialog を表示して確認を取ること

関連コンポーネント

  • IconButton — メニューのトリガーとして使用することが多い
  • ConfirmDialog — 破壊的操作の確認ダイアログ。DropdownMenu の onSelect から呼び出す
  • Select — フォーム入力として選択肢から一つを選ぶ場合はこちらを使用する

On this page