Command
インラインまたは⌘Kパレットとして使える、検索可能な操作リストです。ページ、ショートカット、一致箇所のハイライトに対応します。
pnpm dlx shadcn@latest add https://hextaui.com/r/command.jsonコンポーネント、HextaUIのテーマトークン、依存するHextaUIコンポーネントを追加します。
まだ追加していない場合は、グローバルCSSにテーマトークンを追加してください。
依存関係をインストールします。
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cmdk cn次のコードをコピーしてプロジェクトに貼り付けてください。
components/ui/command.tsx components/ui/button.tsx lib/motion.ts インポートパスは、お使いのプロジェクト構成に合わせて更新してください。
ホットキーでは、Apple デバイスでは mod が ⌘、それ以外では Ctrl を表します。ラベルはプラットフォームごとに自動で整形されます。
基本
入力に応じて、項目の絞り込みと順位付けが行われます。一致のないグループは消え、リストの高さは残りに合わせてアニメーションします。
Dialog
<CommandDialog /> の内側に <Command /> を置き、useCommandHotkey で切り替えます。⌘K または Ctrl K を押してください。項目のショートカットは開いている間に動作し、一致はハイライトされ、preserveSearch は次回開いたときのためにクエリと選択を保持します。
ページ
page を持つ項目は、対応する <CommandPage /> を開きます。ページのタイトルが入力欄内にチップとして表示され、リストは横からスライドインし、検索が空のときの Backspace または Escape で戻ります。
スクロール可能
長いリストは、上限のある高さの中でスクロールします。キーボードで移動している間、選択された項目は常に表示範囲内に保たれます。
非同期の結果
shouldFilter={false} を設定し、取得した結果をレンダリングします。<CommandLoading /> は 150 ms 待ってから表示され、その後は最低 300 ms とどまるため、高速な応答でスピナーが一瞬見えることはありません。両方のレイテンシーを試してみてください。
長いコンテンツ
見出しは折り返され、長い名前は選択に応じて省略または折り返され、ショートカットが押し出されることはありません。
右から左
アイコン、ショートカット、ページチップ、ページのスライドはすべて、読む方向に従います。
| キー | アクション |
|---|---|
| ↓ | 次の項目を選択します。 |
| ↑ | 前の項目を選択します。 |
| Alt↓ | 次のグループの最初の項目に移動します。 |
| Alt↑ | 前のグループの最初の項目に移動します。 |
| Home | 最初の項目を選択します。 |
| End | 最後の項目を選択します。 |
| CtrlN | 次の項目を選択します。Ctrl J でも動作します。vimBindings でオフにできます。 |
| CtrlP | 前の項目を選択します。Ctrl K でも動作します。vimBindings でオフにできます。 |
| Enter | 選択された項目を実行します。リンクの項目では、⌘ Enter または Ctrl Enter で新しいタブで開きます。 |
| Esc | まず検索をクリアし、次にページを 1 つ戻り、最後にダイアログを閉じます。 |
| Backspace | 検索が空のとき、ページを 1 つ戻ります。 |
| ⌘P | 項目のショートカットは、コマンドメニュー内にフォーカスがある間、その項目を実行します。 |
- 入力欄は、選択された項目を指す combobox であり、移動するたびにスクリーンリーダーが各項目を読み上げます。
- polite なライブリージョンが、入力を止めた少し後に結果の件数を通知し、ページを開いたときや離れたときにページタイトルを通知します。文言は
formatResultsとrootTitleで変更できます。 <CommandDialog />は非表示のタイトルと説明を持ち、開いている間はフォーカスを閉じ込め、閉じるとトリガーにフォーカスを戻します。- 項目のショートカットは
aria-keyshortcutsで公開されます。 - モーションの低減が有効な場合、項目は確定の点滅なしで実行され、ページはスライドではなくフェードします。
cmdk をベースにしており、<CommandDialog /> は Base UI のダイアログ上に構築されています。各パーツは、ラップしている cmdk のパーツの props を受け付けます。
| プロパティ | 型 | デフォルト |
|---|---|---|
labelメニューのアクセシブルな名前。 | string | "Command menu" |
highlight各項目の一致した文字をハイライトし、残りを暗くします。 | boolean | false |
shouldFilterfalse に設定すると、項目のフィルタリングと並べ替えを自分で行います。たとえば、結果がサーバーから返ってくる場合です。 | boolean | true |
filter0(非表示)から 1(最も一致)のスコアを返します。 | (value: string, search: string, keywords?: string[]) => number | – |
value選択された項目の値。 | string | – |
defaultValue | string | – |
onValueChange | (value: string) => void | – |
loopリストの端で反対側に回り込みます。 | boolean | false |
vimBindingsCtrl の N、J、P、K による移動。 | boolean | true |
disablePointerSelection | boolean | false |
formatResults入力後にスクリーンリーダーへ通知されるテキスト。 | (count: number) => string | "3 results" |
rootTitle最後のページを離れてルートに戻ったときに通知されます。 | string | "All commands" |
| 属性 | 説明 |
|---|---|
data-slot="command" | CSSでルートを指定します。 |
data-highlighting | ハイライトがオンで、検索が空でない間、付与されます。 |
--command-radius | 外側の角丸の半径。項目はこれから同心の角丸を算出します。 |
--command-inset | リストの端と項目の間のパディング。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChange | (open: boolean, details) => void | – |
preserveSearchダイアログをマウントしたままにするため、閉じてもクエリ、ページ、選択が維持されます。再び開くと、クエリが選択された状態になります。 | boolean | false |
title視覚的に非表示のダイアログのタイトル。 | string | "Command menu" |
description視覚的に非表示のダイアログの説明。 | string | "Search for a command to run." |
showCloseButton | boolean | false |
classNameダイアログのポップアップに適用されます。 | string | – |
| 属性 | 説明 |
|---|---|
data-slot="command-dialog" | ダイアログのポップアップ。 |
data-slot="command-dialog-overlay" | バックドロップ。 |
data-open | ポップアップが開いている間、ポップアップに付与されます。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
value制御された検索テキスト。 | string | – |
onValueChange | (search: string) => void | – |
placeholder | string | – |
clearLabelクリアボタンのアクセシブルな名前。 | string | "Clear search" |
backLabelページチップのアクセシブルな名前。 | (title: string) => string | (title) => `Back from ${title}` |
| 属性 | 説明 |
|---|---|
data-slot="command-input" | 入力欄。 |
data-slot="command-input-wrapper" | アイコン、入力欄、クリアボタンを保持する行。 |
data-slot="command-clear" | 入力すると表示される、クリアボタン。 |
data-slot="command-page-chip" | ページに表示される、戻るチップ。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
labelリストのアクセシブルな名前。 | string | – |
| 属性 | 説明 |
|---|---|
data-slot="command-list" | リスト。 |
data-settled | リストが自分のサイズを計測し終えると付与されます。高さのトランジションは、これが設定されている間だけ実行されます。 |
--cmdk-list-height | 表示されている項目の高さ。リストのアニメーションに使われます。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
childrenクエリをそのまま表示するには、関数形式を使います。 | ReactNode | (search: string) => ReactNode | – |
| 属性 | 説明 |
|---|---|
data-slot="command-empty" | リスト内に CommandLoading がある間は非表示になります。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
loading | boolean | true |
delayスピナーを表示するまでの待機時間(ミリ秒)。 | number | 150 |
minDuration一度表示されたスピナーが最低限とどまる時間(ミリ秒)。 | number | 300 |
labelアクセシブルなラベル。デフォルトは文字列の children です。 | string | – |
progress | number | – |
| 属性 | 説明 |
|---|---|
data-slot="command-loading" | 読み込み中の行。 |
data-pending | 遅延の間、行が通知されているがまだ表示されていないときに付与されます。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
heading | ReactNode | – |
value見出しがない場合は必須です。 | string | – |
forceMountフィルタリング中もグループを表示したままにします。 | boolean | false |
| 属性 | 説明 |
|---|---|
data-slot="command-group" | グループ。 |
[cmdk-group-heading] | 見出し要素。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
onSelectクリック、Enter、または項目のショートカットで、確定の点滅の後に実行されます。 | (value: string) => void | – |
valueフィルタリングに使われます。デフォルトは、ショートカットを除いた項目のテキストです。 | string | – |
keywordsこの項目に一致させる追加の単語。 | string[] | – |
disabled | boolean | false |
shortcut"mod+shift+c" のようなホットキー。項目に表示され、フォーカスがメニュー内にある間、その項目を実行します。 | string | – |
page実行する代わりに、この id を持つ CommandPage を開きます。 | string | – |
pageTitleページチップに表示されるタイトル。デフォルトは value です。 | string | – |
href項目をリンクとしてレンダリングします。Enter でリンクに移動し、⌘ または Ctrl と Enter で新しいタブで開きます。 | string | – |
render代わりにレンダリングするリンク要素。Next.js の <Link /> など。 | ReactElement | – |
confirm選択が伝わるよう、実行する前に項目を短く点滅させます。 | boolean | true |
forceMountフィルタリング中も項目を表示したままにします。 | boolean | false |
| 属性 | 説明 |
|---|---|
data-slot="command-item" | 項目。 |
data-selected="true" | 選択された項目に付与されます。 |
data-disabled="true" | 無効な項目に付与されます。 |
data-value | フィルタリングに使われる値。 |
data-confirming | 確定の点滅中に付与されます。 |
data-page | ページを開く項目に付与されます。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
idそれを開く項目の page prop と一致させます。そのグループと項目は、現在のページである間だけレンダリングされます。 | string | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
hotkey"mod+k" のようなホットキーを、現在のプラットフォーム向けに整形します。children で上書きできます。 | string | – |
| 属性 | 説明 |
|---|---|
data-slot="command-shortcut" | ショートカットのラベル。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
alwaysRender検索中も表示したままにします。 | boolean | false |
| 属性 | 説明 |
|---|---|
data-slot="command-separator" | セパレーター。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
childrenデフォルトは、ページに応じて更新されるキーのヒントです。タッチスクリーンでは非表示になります。 | ReactNode | – |
| 属性 | 説明 |
|---|---|
data-slot="command-footer" | フッター。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
hotkeyドキュメント全体でリッスンされます。修飾キーのないホットキーは、フィールドに入力している間は無視されます。 | string | – |
callback | (event: KeyboardEvent) => void | – |
options.enabled | boolean | true |
<CommandLoading /> と同じ遅延と最小表示時間で、読み込みインジケーターを表示すべきかどうかを返します。リクエスト実行中に古い結果を隠すのに使います。
| プロパティ | 型 | デフォルト |
|---|---|---|
loading | boolean | – |
options.delay | number | 150 |
options.minDuration | number | 300 |
useCommandPages()は、ページを自分のコードから制御するための{ pages, page, push, pop, reset }を返します。useCommandState(selector)は、検索内容や絞り込み後の件数など、cmdk の状態を読み取ります。useHotkeyLabel(hotkey)は、ホットキーを現在のプラットフォーム向けに、⌘K や Ctrl+K のように整形します。
- Buttonすべてのバリアントとサイズのボタンです。読み込み、成功、エラーのフローを内蔵し、高速なリクエストではスピナーを省略します。
- Hotkeyキーボードショートカットの解析、ラベル付け、読み上げ、一致判定を行います。Appleプラットフォームでは⌘、それ以外ではCtrlを使います。
- Motionすべてのコンポーネントがアニメーションに使うイージングカーブ、継続時間、モーション軽減のチェックと、サイズのモーフィングやスライドするハイライト用のフックです。
- SpinnerApple風の目盛りまたは呼吸するリングで表示する読み込みインジケーターです。表示までの待機と、ちらつかない最短表示時間を設定できます。
- Alert dialog破壊的または重要な操作のための確認ダイアログです。非同期処理を待ち、スマートフォンではボトムシートになります。
- Context menu右クリックまたは長押しで開く操作メニューです。サブメニュー、チェックボックス項目、ラジオ項目に対応し、タッチでは長押しのフィードバックを返します。
使用しているブロック
Command の上に構築されるブロック。