マルチコンボボックス
hc-multicombobox は、タグ入力コントロールを備えた複数選択の
コンボボックスです。選択された値は 1 枚の視覚面の中にインラインの
チップとして描画され、フィルタ入力はその隣に住み、リストボックスは
aria-multiselectable="true" を持つため選択のたびに閉じません。
hc-combobox と同じ
アーキテクチャのプリミティブです — WAI-ARIA 1.2 コンボボックス
パターン、HTML popover、CSS Anchor Positioning、DOM フォーカスを
入力に留めたままハイライトを追跡する aria-activedescendant。
別名: マルチセレクト、タグ入力、複数選択コンボボックス。
基本の HTML
Section titled “基本の HTML”- JavaScript
- TypeScript
- Python
- Go
- Rust (coming soon)
<div class="hc-multicombobox" data-name="languages"> <div class="hc-multicombobox__control hc-input"> <span class="hc-multicombobox__tags"></span> <input class="hc-multicombobox__input" type="text" role="combobox" aria-controls="lang-list" aria-label="Languages"> </div>
<ul class="hc-multicombobox__listbox" id="lang-list" role="listbox"> <li class="hc-multicombobox__option" role="option" data-value="js">JavaScript</li> <li class="hc-multicombobox__option" role="option" data-value="ts">TypeScript</li> <li class="hc-multicombobox__option" role="option" data-value="py" aria-selected="true">Python</li> <li class="hc-multicombobox__option" role="option" data-value="go">Go</li> <li class="hc-multicombobox__option" role="option" data-value="rs" aria-disabled="true">Rust</li> </ul></div>import { installMulticombobox } from '@hypermedia-components/core';installMulticombobox();事前に aria-selected="true" が付いたオプションは、シードされたタグに
なります。
| パーツ | 必須 | 用途 |
|---|---|---|
hc-multicombobox | はい | ラッパー。data-name / data-allow-create を持ちます。 |
hc-multicombobox__control | はい | 視覚的なコントロールボックス(hc-input と併用)。 |
hc-multicombobox__tags | はい | ビヘイビアがタグチップで満たす空のコンテナ。 |
hc-multicombobox__input | はい | フィルタ入力 — role="combobox"。 |
hc-multicombobox__listbox | はい | オプションリスト — role="listbox"。 |
hc-multicombobox__option | はい | オプションごとに 1 つ — role="option" + data-value。 |
hc-multicombobox__tag / __tag-remove | 生成 | タグチップとその × 削除ボタン。 |
hc-multicombobox__hidden | 生成 | data-name フォーム統合用の hidden input コンテナ。 |
hc-multicombobox__empty | 生成 | フィルタに一致がない間の「No matches」プレースホルダー。 |
hc-multicombobox__create | 生成 | 合成の「Add …」オプション(data-allow-create)。 |
はいのパーツは著者が書きます。生成のパーツは
installMulticombobox() が作成・削除するので、自分では書かないで
ください。空プレースホルダーのテキストは、リストボックスに
data-hc-empty があればそれ、なければ i18n キー
multicombobox.empty
(i18n カタログ)
です:
<ul class="hc-multicombobox__listbox" id="lang-list" role="listbox" data-hc-empty="No matching language">installMulticombobox() がすること
Section titled “installMulticombobox() がすること”- ARIA: リストボックスに
aria-multiselectable="true"、aria-haspopup="listbox"、aria-autocomplete="list"、aria-expanded、(なければ)aria-controls、ハイライト中の オプションを追跡するaria-activedescendant。 - アンカー結合: 入力にインライン
anchor-name、リストボックスにposition-anchor。CSS Anchor Positioning のないブラウザには JS の 配置フォールバック。 - シード: インストール時点で
aria-selected="true"を持つすべての オプションがタグチップになります — SSR で事前選択された状態が そのまま使えます。 - フィルタリング: キーストロークごとの大文字小文字を無視した
部分文字列一致。何も一致しなければ
.hc-multicombobox__emptyの プレースホルダー。 - トグル選択: ハイライト中のオプションのクリックまたは Enter で 選択状態をトグル。リストボックスは開いたままなので、開き直さずに 複数選べます。
- タグの削除:
- タグの
×ボタンをクリック。 - 入力が空の状態で
Backspaceを押すと最後のタグを削除(タグ入力の 標準的な作法)。
- タグの
- フォーム統合: ラッパーに
data-name="X"があると、ビヘイビアは 選択値ごとに<input type="hidden" name="X" value="…">をラッパー 内に書きます。フォームはネイティブの<select multiple name="X">のようにシリアライズされます。 - イベント: すべての状態変化が、入力上で
detail.{values, added, removed, input}を持つhc:multicomboboxchangeを発火します。
| キー | 動作 |
|---|---|
↓ / ↑ | リストボックスを開く / activedescendant を移動。 |
Home / End | 最初 / 最後の有効な見えるオプション。 |
Enter | ハイライト中のオプションをトグル。 |
Backspace(入力が空) | 最後のタグを削除。 |
Escape | リストボックスを閉じる。選択は保持。 |
Tab | リストボックスを閉じる。通常のタブ順。 |
フォーム統合
Section titled “フォーム統合”ネイティブなフォームシリアライズには、ラッパーに data-name を設定
します:
<form action="/save" method="post"> <div class="hc-multicombobox" data-name="languages">…</div> <button class="hc-button">Save</button></form>languages=js&languages=ts&languages=py として送信されます —
ネイティブの <select multiple name="languages"> が生むのと同じ形
です。PHP / Rails / Python のフレームワークは設定なしでこれをパース
します。
htmx での利用
Section titled “htmx での利用”変更イベントは全状態を運ぶため、編集のたびの htmx スワップは 1 つの トリガー宣言で済みます:
<div class="hc-multicombobox" data-name="languages" data-hx-post="/profile/languages" data-hx-trigger="hc:multicomboboxchange from:closest .hc-multicombobox" data-hx-include="this" data-hx-target="#status"> …</div>サーバは値を永続化し、#status 向けの小さな確認フラグメント
(「Saved」の表示や検証メッセージ)を返します — コントロール自体は
再描画しません。タグと hidden input はクライアント状態です。
非同期オプション — オプションリストをサーバから読み込むには、 代わりにリストボックスの子をスワップします: ビヘイビアはオプションを DOM からライブに読むため、スワップで入った行も静的な行と同じように フィルタ・ハイライト・トグルされます。
<input class="hc-multicombobox__input" type="text" name="q" role="combobox" aria-controls="lang-list" aria-label="Languages" data-hx-get="/languages/options" data-hx-trigger="input changed delay:300ms" data-hx-target="#lang-list" data-hx-swap="innerHTML">サーバは、入力された q に一致する
<li class="hc-multicombobox__option" role="option" data-value="…">
の行だけを返します。
作成可能(creatable)
Section titled “作成可能(creatable)”data-allow-create を足すと、ユーザーはリストにないタグを追加でき
ます。入力したテキストに完全一致がないとき、合成の 「Add …」
オプションが現れます。それを選ぶ(クリックまたは Enter)と
生のテキストからタグが作られ、新しい値を added に載せた
hc:multicomboboxchange が発火します。
<div class="hc-multicombobox" data-name="tags" data-allow-create>…</div>作られたタグのラベルは値そのもので、他のタグと同様に隠し name
input が追加されます。オプションのラベルは
i18n カタログ
(multicombobox.create)で翻訳できます。
リッチなオプション
Section titled “リッチなオプション”オプションには任意の HTML(アイコン + ラベル + 説明)を入れられます。
タグのラベルと一致値には data-label を、フィルタの照合対象
(エイリアス / キーワード)には data-search を使い、リッチ
マークアップのテキストがどちらも汚さないようにします:
- Python scripting
- JavaScript web
- Go services
<div class="hc-multicombobox" data-name="languages"> <div class="hc-multicombobox__control hc-input"> <span class="hc-multicombobox__tags"></span> <input class="hc-multicombobox__input" type="text" role="combobox" aria-controls="lang-rich-list" aria-label="Languages"> </div>
<ul class="hc-multicombobox__listbox" id="lang-rich-list" role="listbox"> <li class="hc-multicombobox__option" role="option" data-value="py" data-label="Python" data-search="python py snake"> <strong>Python</strong> <small>scripting</small> </li> <li class="hc-multicombobox__option" role="option" data-value="js" data-label="JavaScript" data-search="javascript js node"> <strong>JavaScript</strong> <small>web</small> </li> <li class="hc-multicombobox__option" role="option" data-value="go" data-label="Go" data-search="go golang"> <strong>Go</strong> <small>services</small> </li> </ul></div>リッチレイアウトのためにオプションへ display を設定するなら、
フィルタの非表示を上書きしないよう :not([hidden]) にスコープして
ください。
アクセシビリティ
Section titled “アクセシビリティ”- DOM フォーカスは入力に留まり、タイプアヘッドのアンカーが一貫します —
aria-activedescendantが動かすのはハイライトであり、フォーカス ではありません。 - 各タグは
aria-label="Remove …"を持つ本物のフォーカス可能な ボタンなので、スクリーンリーダーの利用者はそこに着地して削除を 実行できます。 - 利用不可の行は
disabledではなくaria-disabled="true"で印を 付けてください(<li>はフォームコントロールではありません)。 - 見える activedescendant のハイライトは
--hc-color-focus-ringを 使い、data-colorテーマに従います。
スコープ外(MVP)
Section titled “スコープ外(MVP)”- タグのドラッグによる並べ替え。
- 非同期のオプション読み込み — 上のドキュメントは htmx スワップの パターンを示しています。組み込みのデバウンス / キャンセルヘルパーは 同梱されません。
テーマ用トークン
Section titled “テーマ用トークン”component トークン(component.tokens.json):
| トークンパス | 用途 |
|---|---|
multicombobox.control.padding-x / padding-y / gap / min-height | タグ入力コントロールのボックス。 |
multicombobox.input.min-width / fg | インラインのテキスト入力。 |
multicombobox.tag.bg / fg / border / padding-x / padding-y / radius / font-size / gap | タグチップ。 |
multicombobox.tag.remove-fg / remove-hover-fg | × ボタン。 |
multicombobox.listbox.* | コンボボックスのリストボックストークンのミラー。 |
multicombobox.option.{padding-x, padding-y, font-size, fg, hover-bg, active-bg, disabled-fg, indicator-size} | オプションのレイアウト + チェックマーク。 |
multicombobox.option.check-color | 選択チェックマークの色(マスク描画なのでアクセントに追従 — 強制カラーでは SelectedItem)。 |
multicombobox.empty-fg | 「No matches」プレースホルダーの色。 |
CSS 変数
Section titled “CSS 変数”生成される CSS 変数を表示
--hc-multicombobox-control-padding-x | -control-padding-y | -control-gap | -control-min-height--hc-multicombobox-input-min-width | -input-fg--hc-multicombobox-tag-bg | -tag-fg | -tag-border | -tag-radius | -tag-gap | -tag-font-size--hc-multicombobox-tag-padding-x | -tag-padding-y--hc-multicombobox-tag-remove-fg | -tag-remove-hover-fg--hc-multicombobox-listbox-bg | -listbox-fg | -listbox-border | -listbox-radius--hc-multicombobox-listbox-max-height | -listbox-padding-block | -listbox-min-width | -listbox-offset--hc-multicombobox-option-padding-x | -option-padding-y | -option-font-size | -option-fg--hc-multicombobox-option-hover-bg | -option-active-bg--hc-multicombobox-option-disabled-fg | -option-indicator-size | -option-check-color--hc-multicombobox-empty-fg