Context Menuとは、右クリック(デスクトップ)または長押し(モバイル)で、操作対象のコンテキストに応じたアクション一覧を表示するUIコンポーネントです。HTML/JavaScriptでは contextmenu イベントを使って独自メニューを開くことが多く、ファイルマネージャーの右クリックメニュー・テキスト選択時のコピー/貼り付けメニュー・Figmaのキャンバス右クリックメニューが典型例です。
この記事を読むと、Context MenuとDropdown Menuの使い分け・contextmenu イベントと onLongPress の実装・コンテキストに応じたメニュー項目の出し分け・ARIA menuパターン・モバイル対応が自分でできるようになります。
まず結論:Context Menuを使う条件
Context Menuを使う条件は、対象を右クリックしたときに、その対象専用の操作が出ると自然な場面です。ファイル、リスト行、キャンバス上のオブジェクト、選択テキストのように、操作対象が明確なUIに向いています。
ただし、Context Menuは発見されにくい補助UIです。削除、共有、編集などの重要操作をContext Menuだけに置くと、右クリックを使わないユーザーやモバイルユーザーが操作できません。主要操作は三点リーダーの Dropdown Menu やツールバーにも置き、Context Menuは近道として使います。
| 判断質問 | Yesなら | Noなら |
|---|---|---|
| 操作対象が明確に選ばれている? | Context Menu向き | Dropdown Menu向き |
| 右クリック/長押しが自然な作業環境? | Context Menu向き | 明示ボタンを優先 |
| その操作がContext Menuにしかない? | NG | 補助UIとしてOK |
| モバイルでも同じ操作が必要? | 三点リーダーも用意 | 長押しだけでも検討可 |
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
操作対象の要素を右クリック(デスクトップ)または長押し(モバイル)することで、その要素に関連したアクション一覧を表示するUIコンポーネント。contextmenu ブラウザイベントをインターセプトして独自UIを表示する形が一般的。
contextmenu は右クリック時に発火するブラウザイベント名です。検索では「contextmenu」と一語で調べられることもありますが、UI設計上の呼び名は Context Menu、実装上のイベント名は contextmenu と分けて考えると整理しやすくなります。
Dropdown MenuとContext Menuの違い:Dropdown Menuは「明示的なトリガーボタンをクリックして開く」——ユーザーが意図的に開く操作を行う。Context Menuは「右クリック(長押し)という暗黙のジェスチャーで開く」——ユーザーが操作対象を認識した状態でのみ自然に開く。発見可能性はDropdown Menuの方が高い。
重要な設計制約:Context Menuは「隠し機能」であるため、Context Menuでしか実行できないアクションを作ってはならない。すべてのアクションは他の手段(三点リーダーボタン・ツールバーなど)でも実行できるようにする。
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- ファイル・アイテム・要素を右クリックすることが自然に期待されるコンテキスト(ファイルマネージャー・デザインツール・スプレッドシート)
- テキスト選択後のコピー・貼り付け・検索などブラウザ標準操作を拡張したい場合
- パワーユーザー向けにキーボードショートカットのヒントを表示する場所として
- すでに Dropdown Menu(三点リーダー)が存在し、その補完的なショートカットとして
3.2 When NOT to use
- Context Menuが唯一のアクション実行手段になる設計 → 発見できないユーザーが操作不能になる
- モバイルのみのアプリ → 長押しは他のジェスチャー(テキスト選択など)と競合する
- 一般コンシューマー向けの単純なUI → 右クリックを発見できないユーザーが多い
3.3 代替UI(Alternatives)
- 主要アクション → 三点リーダー(⋯)の
Dropdown Menu - コンテンツの選択 →
Toggle GroupまたはCheckbox - 素早いアクション実行 →
Command Palette
4. 設計判断の核(Decision Principles)
Context Menuの核は「補助性」——Context Menuにしか存在しないアクションを作ると、右クリックを発見できないユーザーが操作不能になる。すべてのアクションは別の手段でも実行できなければならない。
判断の優先順位:① 補助性の確保(主手段との並列提供)→ ② コンテキスト依存の項目出し分け → ③ モバイル対応 → ④ Separator と破壊的アクションの分離
- コンテキストに応じてメニュー項目を変える:選択されているファイルの種類・状態・権限によって表示する項目を変える。「フォルダを開く」はフォルダにのみ、「画像を編集」は画像ファイルにのみ表示する
- 破壊的アクション(削除)はSeparatorで分離して末尾に配置:誤クリックを防ぐためにSeparatorで区切り、赤色テキストで危険を示す
- よく使う項目を上位に、危険な項目を下位に:認知負荷を下げるために使用頻度の高い項目を上部に配置する。頻度が低い・危険なアクションは下部に置く
- モバイルでは長押しを実装するか、Dropdown Menuのみにするかを選択する:長押しはテキスト選択と競合することが多い。モバイルではContext Menuを省略してDropdown Menuに統一する選択肢も有効
5. 状態設計(States)
5.1 必須状態(Required)
- Closed(閉じた状態):コンテキストメニューは非表示
- Open(展開した状態):右クリック位置の近くに表示、コンテキスト名をヘッダーに表示
5.2 条件付き状態(Conditional)
- Item Hover / Focus:ハイライト表示
- Item Disabled:グレーアウト、
aria-disabled="true"(権限なし・条件未満足) - Item Destructive:赤色テキスト、Separatorで区切り
5.3 State Gallery
| 状態 | 必須 | 何を伝えるか |
|---|---|---|
| Closed | ✅ | 非表示(右クリックで開く) |
| Open | ✅ | コンテキストとアクション一覧 |
| Item Disabled | — | この操作は現在できない |
| Item Destructive | — | 取り消し不能な危険なアクション |
6. バリエーション設計(Variants)
Context Menuはほぼ単一パターン。コンテンツの種類によってメニュー項目が変わる。
| バリアント | コンテキスト | 典型的な項目 |
|---|---|---|
| ファイル操作 | ファイル・フォルダ | 開く・名前変更・コピー・削除 |
| テキスト選択 | 選択されたテキスト | コピー・カット・検索・翻訳 |
| キャンバス | デザインツールのキャンバス | 貼り付け・グループ化・整列 |
| リストアイテム | カード・リスト行 | 編集・複製・アーカイブ・削除 |
禁止パターン:コンテキストメニューのみでアクションを提供する → 発見可能性が低く、キーボードのみのユーザー・モバイルユーザーが操作できない。
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- Context Menuが唯一の操作手段:右クリックを知らないユーザーが操作不能になる最も典型的な失敗パターン
- コンテキストを無視した固定メニュー:ファイルの種類・状態に関わらず常に同じ項目を表示し、「この項目は使えません」という体験が発生する
- 破壊的アクションが他の項目と並列に配置:「名前変更」の隣に「削除」が並び、誤クリックで削除が実行される
7.1 Bad(典型3つ)
- 「削除」機能がContext Menuにのみ存在し、右クリックを知らないユーザーがデータを消せない
- 画像ファイルと文書ファイルで同じメニューが表示され、「画像を編集」ボタンがグレーアウトもされずに文書ファイルで表示される
- 「コピー」と「ゴミ箱に移動」がSeparatorなしで隣接しており、スクロール中に誤って「ゴミ箱に移動」を押してしまう
7.2 Good(対になる3つ)
- 三点リーダーボタンのDropdown Menuと同じアクションをContext Menuでも提供し、「右クリックでも操作できます」とUIのヒントとして示す
- ファイルの種類(
mime_type)に基づいてメニュー項目をフィルタリングし、適用できない項目はメニューに表示しない - 破壊的アクション(ゴミ箱に移動・削除)をSeparatorで区切り、赤色テキストでリストの末尾に配置する
7.3 How to fix(手順)
contextmenuイベントでe.preventDefault()を呼び、独自メニューを表示する- Context Menuのすべての項目を Dropdown Menu(三点リーダー)にも実装して「補助」の位置付けにする
- メニュー項目はコンテキスト(ファイル種類・状態・権限)をベースにフィルタリングして生成する
role="menu"+role="menuitem"のARIAパターンと、Escキーで閉じる処理を実装する
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Keyboard
Shift+F10/Menuキーでフォーカス中の要素のコンテキストメニューを開く(ブラウザ標準)↑・↓でメニュー項目を移動Enterで選択中のアクションを実行Escapeでメニューを閉じる
Focus
- メニューが開いたら最初の
menuitemにフォーカスを移す - 閉じた後、メニューを開いた要素にフォーカスを戻す
Screen Reader
<div
role="menu"
aria-label="report.pdf のコンテキストメニュー"
>
<button role="menuitem">名前を変更</button>
<button role="menuitem">コピー</button>
<div role="separator" aria-hidden="true"></div>
<button role="menuitem" aria-label="ゴミ箱に移動(取り消し不能)">
ゴミ箱に移動
</button>
</div>
Touch / Pointer
- モバイルでは 500ms の長押しでコンテキストメニューを開く
- メニューアイテムのタップ領域は最低44px
- テキスト選択と長押しが競合する場合は
user-select: noneでテキスト選択を無効化するか、長押し対応を省略してDropdown Menuに統一する
Contrast / Readability
- 破壊的アクションの赤色テキストと背景のコントラストは4.5:1以上
- グレーアウトした無効項目のテキストと背景のコントラストは3:1以上(WCAG AA Non-text)
10. 実装メモ(Implementation Notes)
- shadcn/ui の
ContextMenuは@radix-ui/react-context-menuベースで、contextmenuイベントの処理・位置計算・role="menu"ARIAパターン・キーボードナビゲーションがすべて実装済み - 位置計算(画面端での自動反転)は Floating UI が処理する。
@radix-ui/react-context-menuを使う場合は内部で自動処理される - モバイルの長押しは
pointerdownイベント+setTimeout(500ms)で実装する。pointermove/pointerupでタイマーをキャンセルする。ただし iOS Safari ではcontextmenuイベントが長押しで発火する場合もある - コンテキストに応じた動的メニュー生成は、メニュー項目の配列を生成する純粋関数(
getMenuItems(file: FileItem): MenuItem[])として切り出すとテストしやすい
11. 関連リンク
- 関連するUIデザイン原則: フィードバック (Feedback), 段階的開示 (Progressive Disclosure)
- 用語集(定義): アクセシビリティ (Accessibility)
- 関連するUIコンポーネント(横): Dropdown Menu(ドロップダウンメニュー), Command Palette(コマンドパレット), Separator(セパレーター)
12. まとめ
Context Menuの設計で最も重要なルールは「補助性」です——Context Menuにしか存在しないアクションを絶対に作らないこと。迷ったら 4. 設計判断の核 に戻り、主手段との並列提供・コンテキスト依存の出し分け・破壊的アクションの分離の3点を確認してください。shadcn/ui の ContextMenu を使えば位置計算・ARIAパターン・キーボードナビゲーションはすべて解決されます。「知っている人だけ使える便利な近道」として設計することが、Context Menuの正しい位置付けです。