FilterMenu

文字を入力して候補を絞り込み、選択する小さなパネルです。

候補にアイコンとキーを添える・末尾側に開く
当てはまる候補がない時
使えない時・右から左に読む場合

使いどころ

  • ラベル付けや担当の割り当てのように、多めの候補から打って絞り込みながら選ぶ時に使います。
  • 候補が少なく、打って探す必要が無い操作は DropdownMenu を使います。
  • フォームの欄として値を入力・選択する時は、Select・Suggestion・Picker など入力欄のコンポーネントを使います。

使い方

FilterMenuController を filter-menu として登録します。id は画面内で一意にし、label に開く操作の文言、title にパネルの見出し、options に候補を渡します。

見た目は DropdownMenu と同じ白いパネル(1px #bbb の枠、角丸5px、外への柔らかい影)に黒い12pxの文字で、上に一行の入力欄と同じ絞り込みの欄(1px #dedede の枠、角丸2px)、その下に灰色の小さな太字(11px)の見出しと候補を28pxの間隔で並べます。選んだ候補は太字にしてチェックを置き、ホバーした候補と矢印キーで選んでいる候補は角の無い淡い青(--rx-option-active、#ddeefe)に黒い文字にします。ピルで囲みません。使えない候補は文字だけを灰色にします。開閉はその場で切り替え、アニメーションはしません。中に文字の欄を持つため、メニューではなく、コンボボックス(絞り込みの欄)とリストボックス(候補)を載せたパネルにしています。パネルは標準のPopover APIで開き、開く操作に揃えて置きます。Escapeとパネルの外側を押すと閉じます。

開くと前に打った文字を消し、絞り込みの欄へ移ります。打った文字を名前に含む候補だけを残し(大文字と小文字は区別しません)、残った最初の候補を選ぶ位置にします。当てはまる候補が無い時は emptyLabel を出します。

multiple なら開いたまま選択のチェックを切り替え、そうでなければ選んだ一つにチェックを付けて閉じます。一つだけの時は、選んだ候補を選び直しても外れません。候補には icon・shortcut・disabled を添えられます。shortcut は表示だけで、キーの登録は利用側が行います。

選ぶたびに filter-menu:select を出します。name を渡すと、候補ごとに隠し入力を置き、選んだ候補の値だけをフォームで送ります。

createLabel を渡すと絞り込みの欄の隣に作る操作を置き、押すと filter-menu:create を発火し、打った文字を渡します。候補を作ってパネルの候補に加える処理と、選んだ結果の保存は利用側が行います。

JavaScriptなしでもパネルは標準のPopover APIで開閉し、初めから選んだ候補の値は送信されますが、絞り込みと選択はできません。

キーボード

FilterMenuのキーボード操作
キー動作
Enter / Space(開く操作)パネルを開き、絞り込みの欄へ移ります。
文字候補を名前で絞り込みます。
↓ / ↑次・前の選べる候補へ移ります。端では反対の端へ戻ります。
Enter選ぶ位置の候補を選びます。
Escapeパネルを閉じます。

アクセシビリティ

  • 開く操作は aria-haspopup="dialog"・aria-controls を持ち、パネルは title を名前にした role="dialog" です。iconOnly の時は label を開く操作の aria-label にし、icon が無ければ▾のマークを出します。
  • 開く操作の aria-expanded は、controllerがパネルの開閉に合わせて切り替えます。JavaScriptなしでは初期HTMLに書かず、標準のPopover APIの開閉状態をブラウザが伝えます。
  • 絞り込みの欄は role="combobox" で、placeholder を aria-label にし、選ぶ位置の候補を aria-activedescendant で伝えます。
  • 候補は role="listbox" の option で、選んだ状態を aria-selected、選べない候補を aria-disabled で伝えます。multiple の時は aria-multiselectable="true" を付けます。
  • 日本語の変換中の矢印とEnterは、候補の移動や選択に使いません。
  • shortcut の表記は読み上げから外します(aria-hidden)。

イベント

FilterMenuが発火するイベント
イベント内容
filter-menu:select候補を選んだ時。detail は value(候補の値)と selected(選んだ後の状態)です。multiple では外した時に selected が false になります。
filter-menu:create作る操作を押した時。detail.query に絞り込みの欄の文字(前後の空白を除く)を渡します。

API

FilterMenu

ラベル付けや担当の割り当てのように、候補を入力して絞り込みながら選ぶ小さなパネル。見た目はDropdownMenuと同じ白いパネルだが、中に入力欄を持つので、メニューではなくコンボボックス(絞り込みの欄)とリストボックス(候補)の組み合わせにする。選ぶとfilter-menu:selectイベントを発火し、値と選んだかどうかを渡す。

FilterMenuのprops
名前型既定値説明
id必須stringパネルと候補のidの元。画面内で一意にする。パネルは<id>-panel、候補の一覧は<id>-listになる。
label必須string開く操作の名前。
title必須stringパネルの見出し(「ラベルを選ぶ」「担当を決める」など)。
options必須readonly FilterMenuOption[]候補。
multiplebooleanfalse複数を選べる時(ラベル・タグ)。一つだけの時(担当)は選ぶと閉じる。
namestring渡すと、選んだ値をこの名前の隠し入力で送る。
placeholderstring"絞り込む…"絞り込みの欄のプレースホルダー。欄のaria-labelにもなる。
createLabelstring渡すと、絞り込みの欄の隣に「新しく作る」を置き、押すとfilter-menu:createイベントを発火して入力した文字を渡す。
emptyLabelstring"当てはまる候補はありません"当てはまる候補が無い時に出す文言。
iconIconName開く操作の文言の前に置くアイコン。
iconOnlybooleanfalse開く操作をアイコンだけにする。iconが無ければ▾のマークを出す。labelはaria-labelとして読み上げる。
variantButtonProps["variant"]"secondary"開く操作の見た目。値の意味はButtonと同じ。
align"start" | "end""start"パネルを開く操作のどちらの端に揃えるか。endは行の末尾側に置いた操作に使う。
disabledboolean開く操作を押せなくする。

登録するcontroller:filter-menu(FilterMenuController)

読み込むCSS:layers.css、reset.css、tokens.css、base.css、layout.css、components/button.css、components/overlay.css、components/icon.css、components/keycap.css、components/filter-menu.css

FilterMenuOption

FilterMenuOption
名前型既定値説明
value必須string選んだ時に発火するfilter-menu:selectのdetail.valueに入る値。nameがあれば送信する値にもなる。
label必須string候補の名前。絞り込みは、入力した文字をこの名前に含むかで決める(大文字と小文字は区別しない)。
iconIconName選択マークの代わりに前に置くアイコン。渡すと、選択マークは行の末尾に出す。
shortcutstring表示用の補助表記。ショートカットの登録は利用側で行う。
selectedboolean最初から選んでおく。
disabledboolean選べない候補にする。矢印の移動でも飛ばす。

IconName

値:Iconの見本

ButtonProps

Buttonのpropsと同じです。

コード

HTML
Hono JSX