コンポーネント

コンテキストメニュー

右クリックまたは長押しで表示される、ポインターの位置に表示されるメニューです。

import React from 'react';
import * as ContextMenu from '@radix-ui/react-context-menu';
import { DotFilledIcon, CheckIcon, ChevronRightIcon } from '@radix-ui/react-icons';
import './styles.css';
const ContextMenuDemo = () => {
const [bookmarksChecked, setBookmarksChecked] = React.useState(true);
const [urlsChecked, setUrlsChecked] = React.useState(false);
const [person, setPerson] = React.useState('pedro');
return (
<ContextMenu.Root>
<ContextMenu.Trigger className="ContextMenuTrigger">Right-click here.</ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent" sideOffset={5} align="end">
<ContextMenu.Item className="ContextMenuItem">
Back <div className="RightSlot">⌘+[</div>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem" disabled>
Forward <div className="RightSlot">⌘+]</div>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem">
Reload <div className="RightSlot">⌘+R</div>
</ContextMenu.Item>
<ContextMenu.Sub>
<ContextMenu.SubTrigger className="ContextMenuSubTrigger">
More Tools
<div className="RightSlot">
<ChevronRightIcon />
</div>
</ContextMenu.SubTrigger>
<ContextMenu.Portal>
<ContextMenu.SubContent className="ContextMenuSubContent" sideOffset={2} alignOffset={-5} >
<ContextMenu.Item className="ContextMenuItem">
Save Page As… <div className="RightSlot">⌘+S</div>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem">Create Shortcut…</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem">Name Window…</ContextMenu.Item>
<ContextMenu.Separator className="ContextMenuSeparator" />
<ContextMenu.Item className="ContextMenuItem">Developer Tools</ContextMenu.Item>
</ContextMenu.SubContent>
</ContextMenu.Portal>
</ContextMenu.Sub>
<ContextMenu.Separator className="ContextMenuSeparator" />
<ContextMenu.CheckboxItem className="ContextMenuCheckboxItem" checked={bookmarksChecked} onCheckedChange={setBookmarksChecked} >
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<CheckIcon />
</ContextMenu.ItemIndicator>
Show Bookmarks <div className="RightSlot">⌘+B</div>
</ContextMenu.CheckboxItem>
<ContextMenu.CheckboxItem className="ContextMenuCheckboxItem" checked={urlsChecked} onCheckedChange={setUrlsChecked} >
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<CheckIcon />
</ContextMenu.ItemIndicator>
Show Full URLs
</ContextMenu.CheckboxItem>
<ContextMenu.Separator className="ContextMenuSeparator" />
<ContextMenu.Label className="ContextMenuLabel">People</ContextMenu.Label>
<ContextMenu.RadioGroup value={person} onValueChange={setPerson}>
<ContextMenu.RadioItem className="ContextMenuRadioItem" value="pedro">
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<DotFilledIcon />
</ContextMenu.ItemIndicator>
Pedro Duarte
</ContextMenu.RadioItem>
<ContextMenu.RadioItem className="ContextMenuRadioItem" value="colm">
<ContextMenu.ItemIndicator className="ContextMenuItemIndicator">
<DotFilledIcon />
</ContextMenu.ItemIndicator>
Colm Tuite
</ContextMenu.RadioItem>
</ContextMenu.RadioGroup>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
};
export default ContextMenuDemo;

特徴

    設定可能な読み取り方向を持つサブメニューをサポートします。

    項目、ラベル、項目のグループをサポートします。

    オプションで不確定状態を持つ、チェック可能な項目(単一または複数)をサポートします。

    モーダルモードと非モーダルモードをサポートします。

    側面、配置、オフセット、衝突処理をカスタマイズできます。

    フォーカスは完全に管理されます。

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

    タイプアヘッドをサポートします。

    破棄とレイヤーの動作は高度にカスタマイズ可能です。

    タッチデバイスでの長押しでトリガーします

インストール

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

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

構造

すべてのパーツをインポートして組み立てます。

import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger />
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Label />
<ContextMenu.Item />
<ContextMenu.Group>
<ContextMenu.Item />
</ContextMenu.Group>
<ContextMenu.CheckboxItem>
<ContextMenu.ItemIndicator />
</ContextMenu.CheckboxItem>
<ContextMenu.RadioGroup>
<ContextMenu.RadioItem>
<ContextMenu.ItemIndicator />
</ContextMenu.RadioItem>
</ContextMenu.RadioGroup>
<ContextMenu.Sub>
<ContextMenu.SubTrigger />
<ContextMenu.Portal>
<ContextMenu.SubContent />
</ContextMenu.Portal>
</ContextMenu.Sub>
<ContextMenu.Separator />
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);

APIリファレンス

メニューの WAI-ARIA デザインパターン に準拠しており、メニュー項目間のフォーカス移動を管理するために ロービング tabindex を使用しています。

ルート

コンテキストメニューのすべての部分を含みます。

プロパティデフォルト
dir
enum
デフォルト値なし
onOpenChange
関数
デフォルト値なし
modal
真偽値
true

トリガー

コンテキストメニューを開く領域です。右クリック(または関連するキーボードショートカットを使用)したときにコンテキストメニューを開きたいターゲットをラップします。

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

ポータル

使用すると、コンテンツ部分を body にポータルします。

プロパティデフォルト
forceMount
真偽値
デフォルト値なし
コンテナ
HTMLElement
document.body

コンテンツ

開いているコンテキストメニューでポップアウトするコンポーネントです。

プロパティデフォルト
asChild
真偽値
false
loop
真偽値
false
onCloseAutoFocus
関数
デフォルト値なし
onEscapeKeyDown
関数
デフォルト値なし
onPointerDownOutside
関数
デフォルト値なし
onFocusOutside
関数
デフォルト値なし
onInteractOutside
関数
デフォルト値なし
forceMount
真偽値
デフォルト値なし
alignOffset
数値
0
avoidCollisions
真偽値
true
collisionBoundary
境界
[]
collisionPadding
数値 | パディング
0
sticky
enum
"partial"
hideWhenDetached
真偽値
false
データ属性
[data-state]"open" |"closed"
[data-side]"left" |"right" |"bottom" |"top"
[data-align]"start" |"end" |"center"
CSS変数説明
--radix-context-menu-content-transform-originコンテンツと矢印の位置/オフセットから計算された transform-origin
--radix-context-menu-content-available-widthトリガーと境界エッジ間の残りの幅
--radix-context-menu-content-available-heightトリガーと境界エッジ間の残りの高さ
--radix-context-menu-trigger-widthトリガーの幅
--radix-context-menu-trigger-heightトリガーの高さ

矢印

サブメニューと一緒にレンダリングするオプションの矢印要素。これは、トリガー項目を ContextMenu.Content と視覚的にリンクするのに役立ちます。 ContextMenu.Content の内部でレンダリングする必要があります。

プロパティデフォルト
asChild
真偽値
false
数値
10
高さ
数値
5

項目

コンテキストメニュー項目を含むコンポーネントです。

プロパティデフォルト
asChild
真偽値
false
disabled
真偽値
デフォルト値なし
onSelect
関数
デフォルト値なし
textValue
文字列
デフォルト値なし
データ属性
[data-highlighted]

ハイライトされている場合に表示されます

[data-disabled]

無効になっている場合に表示されます

グループ

複数の ContextMenu.Item をグループ化するために使用します。

プロパティデフォルト
asChild
真偽値
false

ラベル

ラベルをレンダリングするために使用します。矢印キーを使用してフォーカスすることはできません。

プロパティデフォルト
asChild
真偽値
false

CheckboxItem

チェックボックスのように制御およびレンダリングできる項目。

プロパティデフォルト
asChild
真偽値
false
checked
真偽値 | 'indeterminate'
デフォルト値なし
onCheckedChange
関数
デフォルト値なし
disabled
真偽値
デフォルト値なし
onSelect
関数
デフォルト値なし
textValue
文字列
デフォルト値なし
データ属性
[data-state]"checked" |"unchecked" |"indeterminate"
[data-highlighted]

ハイライトされている場合に表示されます

[data-disabled]

無効になっている場合に表示されます

RadioGroup

複数の ContextMenu.RadioItem をグループ化するために使用します。

プロパティデフォルト
asChild
真偽値
false
value
文字列
デフォルト値なし
onValueChange
関数
デフォルト値なし

RadioItem

ラジオのように制御およびレンダリングできる項目。

プロパティデフォルト
asChild
真偽値
false
value*
文字列
デフォルト値なし
disabled
真偽値
デフォルト値なし
onSelect
関数
デフォルト値なし
textValue
文字列
デフォルト値なし
データ属性
[data-state]"checked" |"unchecked" |"indeterminate"
[data-highlighted]

ハイライトされている場合に表示されます

[data-disabled]

無効になっている場合に表示されます

ItemIndicator

親の ContextMenu.CheckboxItem または ContextMenu.RadioItem がチェックされている場合にレンダリングします。この要素を直接スタイル設定するか、アイコンを入れるためのラッパーとして使用するか、またはその両方を行うことができます。

プロパティデフォルト
asChild
真偽値
false
forceMount
真偽値
デフォルト値なし
データ属性
[data-state]"checked" |"unchecked" |"indeterminate"

Separator

コンテキストメニュー内の項目を視覚的に分離するために使用します。

プロパティデフォルト
asChild
真偽値
false

サブ

サブメニューのすべての部分を含みます。

プロパティデフォルト
defaultOpen
真偽値
デフォルト値なし
open
真偽値
デフォルト値なし
onOpenChange
関数
デフォルト値なし

SubTrigger

サブメニューを開く項目。ContextMenu.Sub の内部でレンダリングする必要があります。

プロパティデフォルト
asChild
真偽値
false
disabled
真偽値
デフォルト値なし
textValue
文字列
デフォルト値なし
データ属性
[data-state]"open" |"closed"
[data-highlighted]

ハイライトされている場合に表示されます

[data-disabled]

無効になっている場合に表示されます

SubContent

サブメニューが開いているときにポップアウトするコンポーネント。ContextMenu.Sub の内部でレンダリングする必要があります。

プロパティデフォルト
asChild
真偽値
false
loop
真偽値
false
onEscapeKeyDown
関数
デフォルト値なし
onPointerDownOutside
関数
デフォルト値なし
onFocusOutside
関数
デフォルト値なし
onInteractOutside
関数
デフォルト値なし
forceMount
真偽値
デフォルト値なし
sideOffset
数値
0
alignOffset
数値
0
avoidCollisions
真偽値
true
collisionBoundary
境界
[]
collisionPadding
数値 | パディング
0
arrowPadding
数値
0
sticky
enum
"partial"
hideWhenDetached
真偽値
false
データ属性
[data-state]"open" |"closed"
[data-side]"left" |"right" |"bottom" |"top"
[data-align]"start" |"end" |"center"
CSS変数説明
--radix-context-menu-content-transform-originコンテンツと矢印の位置/オフセットから計算された transform-origin
--radix-context-menu-content-available-widthトリガーと境界エッジ間の残りの幅
--radix-context-menu-content-available-heightトリガーと境界エッジ間の残りの高さ
--radix-context-menu-trigger-widthトリガーの幅
--radix-context-menu-trigger-heightトリガーの高さ

サブメニュー付き

ContextMenu.Sub をその部品と組み合わせて使用​​することで、サブメニューを作成できます。

<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Sub>
<ContextMenu.SubTrigger>Sub menu →</ContextMenu.SubTrigger>
<ContextMenu.Portal>
<ContextMenu.SubContent>
<ContextMenu.Item>Sub menu item</ContextMenu.Item>
<ContextMenu.Item>Sub menu item</ContextMenu.Item>
<ContextMenu.Arrow />
</ContextMenu.SubContent>
</ContextMenu.Portal>
</ContextMenu.Sub>
<ContextMenu.Separator />
<ContextMenu.Item></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>

無効な項目付き

data-disabled 属性を介して、無効な項目に特別なスタイルを追加できます。

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item className="ContextMenuItem" disabled>
</ContextMenu.Item>
<ContextMenu.Item className="ContextMenuItem"></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* styles.css */
.ContextMenuItem[data-disabled] {
color: gainsboro;
}

区切り線付き

Separator 部品を使用して、項目間に区切り線を追加します。

<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>

ラベル付き

Label 部品を使用して、セクションのラベル付けを支援します。

<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Label>Label</ContextMenu.Label>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>

チェックボックス項目付き

CheckboxItem 部品を使用して、チェックできる項目を追加します。

import React from 'react';
import { CheckIcon } from '@radix-ui/react-icons';
import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => {
const [checked, setChecked] = React.useState(true);
return (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Item></ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.CheckboxItem checked={checked} onCheckedChange={setChecked} >
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Checkbox item
</ContextMenu.CheckboxItem>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
};

ラジオ項目付き

RadioGroup および RadioItem 部品を使用して、他の項目の中でチェックできる項目を追加します。

import React from 'react';
import { CheckIcon } from '@radix-ui/react-icons';
import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => {
const [color, setColor] = React.useState('blue');
return (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.RadioGroup value={color} onValueChange={setColor}>
<ContextMenu.RadioItem value="red">
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Red
</ContextMenu.RadioItem>
<ContextMenu.RadioItem value="blue">
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Blue
</ContextMenu.RadioItem>
<ContextMenu.RadioItem value="green">
<ContextMenu.ItemIndicator>
<CheckIcon />
</ContextMenu.ItemIndicator>
Green
</ContextMenu.RadioItem>
</ContextMenu.RadioGroup>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
};

複雑な項目付き

画像など、装飾的な要素を Item 部品に追加できます。

import * as ContextMenu from '@radix-ui/react-context-menu';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content>
<ContextMenu.Item>
<img src="" />
Adolfo Hess
</ContextMenu.Item>
<ContextMenu.Item>
<img src="" />
Miyah Myles
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);

コンテンツ/サブコンテンツのサイズを制約する

コンテンツ(またはサブコンテンツ)の幅をトリガー(またはサブトリガー)の幅に合わせて制約したい場合があります。また、高さをビューポートを超えないように制約したい場合があります。

これをサポートするために、 --radix-context-menu-trigger-width--radix-context-menu-content-available-height などのいくつかの CSS カスタムプロパティを公開しています。これらを使用して、コンテンツの寸法を制約します。

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent">
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* styles.css */
.ContextMenuContent {
width: var(--radix-context-menu-trigger-width);
max-height: var(--radix-context-menu-content-available-height);
}

原点対応アニメーション

CSS カスタムプロパティ --radix-context-menu-content-transform-origin を公開しています。これを使用して、 sidesideOffsetalignalignOffset 、および衝突に基づいて計算された原点からコンテンツをアニメーション化します。

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent">
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* styles.css */
.ContextMenuContent {
transform-origin: var(--radix-context-menu-content-transform-origin);
animation: scaleIn 0.5s ease-out;
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0);
}
to {
opacity: 1;
transform: scale(1);
}
}

衝突対応アニメーション

data-side および data-align 属性を公開します。それらの値は、衝突を反映するために実行時に変化します。これらを使用して、衝突と方向に対応したアニメーションを作成します。

// index.jsx
import * as ContextMenu from '@radix-ui/react-context-menu';
import './styles.css';
export default () => (
<ContextMenu.Root>
<ContextMenu.Trigger></ContextMenu.Trigger>
<ContextMenu.Portal>
<ContextMenu.Content className="ContextMenuContent">
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu.Root>
);
/* styles.css */
.ContextMenuContent {
animation-duration: 0.6s;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.ContextMenuContent[data-side='top'] {
animation-name: slideUp;
}
.ContextMenuContent[data-side='bottom'] {
animation-name: slideDown;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

アクセシビリティ

メニュー項目間のフォーカス移動を管理するために、 ロービング tabindex を使用しています。

キーボード操作

キー説明
Space
フォーカスされている項目をアクティブにします。
Enter
フォーカスされている項目をアクティブにします。
ArrowDown
フォーカスを次の項目に移動します。
ArrowUp
フォーカスを前の項目に移動します。
ArrowRightArrowLeft
フォーカスが ContextMenu.SubTrigger にある場合、読み取り方向に応じてサブメニューを開閉します。
Esc
コンテキストメニューを閉じます
次へDialog