CommandMenu

ヘッダーの末尾側に置く検索欄から開き、アプリ全体の移動先と操作を名前で探します。

「操作イベントを試す」を選ぶと、受け取った値をここに表示します。

使いどころ

  • アプリ全体の移動先と操作を一か所から探す検索として、AppShellのcommandsに一つ置きます。ヘッダーの末尾側、主な移動先の後ろに並びます。
  • よく使う場所はshortcutsのタイル、最近の場所・人・ページ・操作はgroupsの一覧に分けて渡します。
  • 画面の中の一つの対象に対する操作の一覧はDropdownMenu、同じ領域のページの切り替えはNavigation、作業面の中の階層はTreeを使います。
  • 開閉のキー(shortcut)は、アプリ全体で一つのCommandMenuだけに指定します。

使い方

id・label・shortcuts・groupsを渡し、CommandMenuControllerをcommand-menuとして登録します。labelは開くボタンとパネルの見出しに出す名前です。開くボタンは、Basecamp 2のヘッダーの検索欄と同じ見た目にします。枠の無い白い欄(高さ32px、角丸3px)をシートと同じ四方へのぼかしの影で浮かせ、icon(既定はlayers)と淡い灰色のlabelを先頭から並べ、326px(20.375rem)以上の幅を取ります。パネルを開いている間は、欄にフォーカスがある時と同じ青い縁と淡い青の輪を付けます。

開くボタンを押すと、背景を暗転しないpopover="auto"のパネルを開きます。パネルは枠を持たず、四方へ約10pxのぼかしの影で浮かせた白いパネル(角丸5px、幅30remまで)で、画面の上端から1remの位置の中央に、動きを付けずにその場で現れます。中は見出し、shortcutsのタイル(columnsの列数、既定は4列で、パネルが狭い時は2列)、検索欄、候補の一覧、キーの案内の順です。候補の一覧はBasecamp 2のジャンプの候補と同じ二列で、左の112pxの列にまとまりの名前(12pxの灰色、右寄せ。長い名前は文節で折り返す)を置き、1pxのごく淡い罫線(#f5f5f5)で区切った右の列に、候補を高さ25pxの行で隙間なく並べます。まとまりの間と、検索欄・キーの案内との間も同じ罫線で区切ります。ホバーした候補と矢印キーで選んでいる候補は、右の列だけをDropdownMenuと同じ角の無い淡い青(#ddeefe)で塗り、文字は黒のままにします。パネルの幅が20rem未満では、まとまりの名前を候補の上に積みます。ピルでは囲みません。開くたびに検索欄を空にして全候補を出し、検索欄へフォーカスを移します。先頭の候補を選んだ状態で始まります。移動や操作の項目を選ぶ、閉じるボタンかEscを押す、パネルの外を押す、フォーカスがパネルの外へ移る、のいずれかで閉じます。Turboのキャッシュの直前(turbo:before-cache)にも閉じます。

検索欄の文字は、各項目のlabel・description・keywordsをつないだ文字列と照合します。空白で区切った語をすべて含む項目だけを残し、全角と半角、大文字と小文字は区別しません。項目の残らないグループは隠し、一件も残らなければ「見つかりませんでした。」を出します。shortcutsは絞り込みの対象外です。

groupsの項目は、hrefを渡すと移動のリンク、valueを渡すと操作のボタンになります。移動は通常のリンクとして画面を移ります。操作を選ぶとパネルを閉じて開くボタンへフォーカスを戻し、command-menu:selectを発火してdetail.valueを渡します。操作の実行は利用側のcontrollerが担い、actionにcommand-menu:select->(controller名)#(メソッド名)の形で受け取り先を書きます。

shortcutを指定すると、ページのどこからでもそのキーで開閉し、パネルの下にキーの案内を出します。shift+jは入力欄・テキストエリア・選択欄・編集できる要素の中では働かず、mod+kは入力中も働きます。どちらも、Altを押している時、キーを押し続けた繰り返し、日本語の変換中、開くボタンが無効か表示されていない時は働きません。開いている時に押すと閉じて、開くボタンへフォーカスを戻します。

JavaScriptなしでも、開くボタンと閉じるボタンはpopovertargetでパネルを開閉し、ショートカットと移動の項目は通常のリンクとして動作します。絞り込み、矢印キーの選択、操作の項目の実行、開閉のキーはcontrollerが担います。

キーボード

CommandMenuのキーボード操作
キー動作
Ctrl+K / Cmd+Kshortcut="mod+k"の時、ページのどこからでもパネルを開閉します。入力中も働きます。
Shift+Jshortcut="shift+j"の時、入力欄の外でパネルを開閉します。
↓ / ↑検索欄か候補の中で、次・前の候補を選びます。無効な項目は飛ばし、端で止まります。候補の中では、選んだ候補へフォーカスも移ります。
Home / End候補の中で、先頭・末尾の候補を選びます。検索欄では文字の移動のままです。
Enter検索欄で、選んでいる候補を実行します。リンクは移動し、操作はcommand-menu:selectを発火します。日本語の変換中は実行しません。
Escパネルを閉じ、開くボタンへフォーカスを戻します。
Tabパネルの中の閉じるボタン・ショートカット・検索欄・候補を順に移ります。パネルの外へ出ると閉じます。

アクセシビリティ

  • 開くボタンはaria-haspopup="dialog"・aria-controls・aria-expandedを持ちます。shortcutを指定すると、aria-keyshortcutsでキーを伝えます。
  • パネルはrole="dialog"で、「(label)のコマンド」という読み上げ名を持ちます。ショートカットの並びは「よく使う場所」という読み上げ名のnavです。
  • 検索欄はrole="combobox"、候補の一覧はrole="tree"、各項目はrole="treeitem"です。フォーカスを検索欄に残したまま、選んでいる候補をaria-activedescendantとaria-selectedで伝えます。
  • 絞り込むたびに、候補の件数をrole="status"で読み上げます。
  • 現在地の項目はaria-current="page"と「現在地」の読み上げで伝えます。無効な項目はaria-disabled="true"です。
  • descriptionは、一覧の移動の項目では名前の後に表示し、操作の項目とショートカットのタイルでは画面に出さずaria-descriptionで読み上げます(無効なショートカットでも保ちます)。見える名前だけで選べるようにし、欠かせない情報をdescriptionだけに置きません。

イベント

CommandMenuが発火するイベント
イベント内容
command-menu:selectvalueを持つ操作の項目を選んだ時に、ルートから発火します。detail.valueは項目のvalueです。

API

CommandMenu

主要なショートカットと、仕事・人・ページへの移動を一つの場所へまとめる。

CommandMenuのprops
名前型既定値説明
id必須stringパネルのid。開くボタンのpopovertargetと、検索欄・結果の各idの元になる。ページ内で一意にする。
label必須string開くボタンとパネルの見出しに出す名前(チーム名・アプリ名など)。パネルの読み上げ名にも使う。
shortcuts必須readonly CommandLink[]検索欄の上にグリッドで並べる主要なショートカット。空にするとショートカットの段を出さない。
groups必須readonly CommandGroup[]検索欄の下に並べる候補のグループ(最近の場所・人・ページ・操作など)。検索でこの中を絞り込む。
columns3 | 44ショートカットの段の列数。パネルが狭い時は2列にする。
iconIconName"layers"開くボタンの名前の前のアイコン。
shortcut"shift+j" | "mod+k"開閉のキー。shift+jはShift+J、mod+kはCtrlまたはCmdとKで開閉し、パネルの下にキーの案内を出す。省略するとキーを登録しない。アプリ全体で一つのCommandMenuだけに指定する。
actionstringルートのdata-action。command-menu:selectを受け取るcontrollerのアクションを書く。

登録するcontroller:command-menu(CommandMenuController)

読み込むCSS:layers.css、reset.css、tokens.css、base.css、layout.css、components/command-menu.css、components/badge.css、components/button.css、components/action-tile.css、components/overlay.css、components/icon.css、components/input-group.css、components/keycap.css

CommandLink

CommandLink
名前型既定値説明
label必須string項目の名前。一覧の項目では検索の対象になる。
descriptionstring名前に添える補足。一覧の移動の項目では名前の後に表示し、操作の項目とショートカットのタイルでは画面に出さずaria-descriptionで読み上げる。一覧の項目では検索の対象になる。
iconIconName名前の前のアイコン。移動の項目とショートカットで省略すると矢印のアイコンになる。操作の項目で省略するとアイコンを出さない。
keywordsreadonly string[]画面には出さない検索語。別名や関連語を渡すと、その言葉でも絞り込める。
disabledboolean選べない状態で表示する。リンクは移動せず、操作は押せず、矢印キーの移動の対象から外す。理由は名前や補足で伝える。
accent"blue" | "green" | "amber" | "coral"アイコンの色。ショートカットのタイルと、一覧の移動の項目のアイコンに使う。
href必須string移動先のURL。選ぶと通常のリンクとして移動し、パネルを閉じる。
currentboolean今いる場所。aria-current="page"を付け、一覧では末尾側にチェックマークを出す。

CommandGroup

CommandGroup
名前型既定値説明
label必須stringグループの見出し(「最近の場所」など)。
items必須readonly CommandItem[]グループの項目。hrefを持つ項目は移動、valueを持つ項目は操作になる。空のグループは表示しない。

IconName

値:Iconの見本

CommandItem

CommandItem(href・currentを持つ形)
名前型既定値説明
label必須string項目の名前。一覧の項目では検索の対象になる。
descriptionstring名前に添える補足。一覧の移動の項目では名前の後に表示し、操作の項目とショートカットのタイルでは画面に出さずaria-descriptionで読み上げる。一覧の項目では検索の対象になる。
iconIconName名前の前のアイコン。移動の項目とショートカットで省略すると矢印のアイコンになる。操作の項目で省略するとアイコンを出さない。
keywordsreadonly string[]画面には出さない検索語。別名や関連語を渡すと、その言葉でも絞り込める。
disabledboolean選べない状態で表示する。リンクは移動せず、操作は押せず、矢印キーの移動の対象から外す。理由は名前や補足で伝える。
accent"blue" | "green" | "amber" | "coral"アイコンの色。ショートカットのタイルと、一覧の移動の項目のアイコンに使う。
href必須string移動先のURL。選ぶと通常のリンクとして移動し、パネルを閉じる。
currentboolean今いる場所。aria-current="page"を付け、一覧では末尾側にチェックマークを出す。
CommandItem(valueを持つ形)
名前型既定値説明
label必須string項目の名前。一覧の項目では検索の対象になる。
descriptionstring名前に添える補足。一覧の移動の項目では名前の後に表示し、操作の項目とショートカットのタイルでは画面に出さずaria-descriptionで読み上げる。一覧の項目では検索の対象になる。
iconIconName名前の前のアイコン。移動の項目とショートカットで省略すると矢印のアイコンになる。操作の項目で省略するとアイコンを出さない。
keywordsreadonly string[]画面には出さない検索語。別名や関連語を渡すと、その言葉でも絞り込める。
disabledboolean選べない状態で表示する。リンクは移動せず、操作は押せず、矢印キーの移動の対象から外す。理由は名前や補足で伝える。
accent"blue" | "green" | "amber" | "coral"アイコンの色。ショートカットのタイルと、一覧の移動の項目のアイコンに使う。
value必須string操作の値。選ぶとcommand-menu:selectイベントを発火し、detail.valueで渡す。実行は利用側が担う。

コード

HTML
Hono JSX