Skip to content
fandhe-frontendcore v0.4.3
GitHub

Command

検索入力 + 絞り込み済みリスト + グループ + ショートカット表示 + dialog 内表示を組み合わせたコマンドパレット相当の shadcn/ui Command(cmdk 由来)部品です(参照軸はイシュー #2001、shadcn/ui 追加はイシュー #2004)。fandhe-frontend-headless-ui の command mod が構造・アクセシビリティ(WAI-ARIA)・表示状態(data-*)のみを提供する unstyled 部品で、root / input / list / empty / group / group-heading / item / shortcut / separator / dialog の 10 anatomy パーツを持ちます。

既存の combobox(ARIA 1.2 combobox パターン)・listbox(role="listbox"/role="option")の ARIA 実装を再利用し、新規の意味論は持ち込みません。Command 状態機械(Disclosure + TextInput + SingleSelect を合成)は cmdk のコマンドパレット意味論に合わせ、入力(Input)は dialog を開閉せず、選択(Select)も dialog を閉じません(実行フックはアプリケーションロジックとして UI コンポーネント層の範囲外です)。

アクセシビリティ

  • input は role="combobox" + aria-controls(必須引数)+ aria-autocomplete="list" を固定付与します。aria-controls を必須引数にすることで、aria-controls/aria-expanded の関連付けを型で構造的に満たします。
  • list は role="listbox" を固定付与し、id/aria-label を必須引数にすることでアクセシブルネームを型で強制します。
  • item は role="option" + aria-selected + data-selected(presence)で選択有無を表します。data-highlighted/data-state は出力しません(combobox/listbox との意図的な差分。aria-activedescendant が指すのは「確定選択中の item」であり「キーボードでハイライト中の行」ではないため)。
  • dialog は role="dialog" + aria-modal="true" + tabindex="-1" を固定付与し、label が空文字列でないときのみ aria-label を付与します。closed のとき hidden 存在属性を付与します。
  • group は labelledby が Some のときのみ role="group" + aria-labelledby を出力します。group-heading の id が参照先になります。
  • root/list/empty はいずれも empty: bool 引数を取り、絞り込み結果 0 件のとき data-empty を出力します。表示切替(hidden 等)は呼び出し側または pre-styled-ui の CSS の責務です。
  • キーボード操作(矢印キー・Enter・Escape・Cmd/Ctrl+K)の実 DOM 配線は fandhe-frontend-wasm-full の command モジュールが実装済みです(入力絞り込み・行選択・実行フック・dialog 開閉、イシュー #2069)。

自前 CSS の最小例:

CSS
[data-scope="command"][data-part="root"][data-empty] {
  min-height: 4rem;
}
[data-scope="command"][data-part="item"][data-selected] {
  background: #eef;
}
[data-scope="command"][data-part="item"][data-disabled] {
  opacity: 0.5;
}
[data-scope="command"][data-part="dialog"][hidden] {
  display: none;
}

fandhe-frontend-pre-styled-ui に対応するスタイル済み部品があります。Themes 版は Command を参照してください。

関連 API: fandhe-frontend-headless-ui API

Demo

枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。

Suggestions
Calendar⌘C
Settings
No results found.
No results found.

Features

  • root/input/list/empty/group/group_heading/item/shortcut/separator/dialog の 10 anatomy パーツを持ち、combobox/listbox の既存 ARIA 実装(role="combobox"/role="listbox"/role="option")を再利用する(command.rs 冒頭参照)。
  • input は role="combobox" + aria-controls(必須引数)+ aria-autocomplete="list" を固定付与し、docs-site の R1〜R4 契約を型で構造的に満たす(Option opt-in にしない、command.rs「input の ARIA」節)。
  • item は data-selected(presence)+ aria-selected で選択有無を表し、data-highlighted/data-state は出力しない(combobox/listbox との意図的な差分、command.rs「item の選択表現」節)。
  • root/list/empty はいずれも empty: bool 引数を取り、絞り込み結果 0 件のとき data-empty を出力する。表示切替(hidden 等)は呼び出し側/pre-styled-ui の CSS の責務(command.rs「data-empty の付与先と SSR 決定性」節)。
  • Command 状態機械は Input で dialog を開閉せず、Select で dialog を閉じない(cmdk のコマンドパレット意味論。実行フックは UI コンポーネント層の責務外、command.rs参照)。
  • filter_items は crate::combobox::filter_options へ全委譲する(新規の絞り込みアルゴリズムを持ち込まない)。

Anatomy

dialog
  root
    input
    list
      group
        group-heading
        item
          shortcut
      separator
    empty

API Reference

Arguments

NameTypeDefaultDescription
root(state, empty) / dialog(state, label)OpenState, bool / OpenState, &strOpenState::Closed, falsedialog 開閉状態と絞り込み結果 0 件かどうか。dialog の label は空文字列のとき aria-label を省略する。
input(state, value, list_id, activedescendant)OpenState, &str, &str, Option<&str>—現在のクエリ・aria-controls の参照先(必須)・選択中 item の id。
list(id, label, empty)&str, &str, bool—role="listbox" の id(必須)・aria-label(必須)・絞り込み結果 0 件かどうか。
item(selected, disabled, value, id)bool, bool, &str, Option<&str>—role="option" を持つ候補 1 個の選択状態・無効化・value(data-value として出力)・id。
group(labelledby) / group_heading(id)Option<&str> / Option<&str>—labelledby が Some のときのみ role="group"/aria-labelledby を出力する。group_heading の id が参照先になる。
filter_items(items, query) / Command::filtered_items / is_empty&[(&str, &str)], &str—crate::combobox::filter_options への全委譲(大文字小文字非区別の部分一致・入力順保持)。
attrs / childrenVec<(&str, &str)> / Vec<Node>—各パーツ共通の追加属性・子ノード(代表 1 行に集約)。

Data Attributes

PartAttributeObserved Values
dialogdata-stateopen
emptydata-empty(値なし)
inputdata-stateopen
itemdata-disabled(値なし)
itemdata-selected(値なし)
itemdata-valuecalendar, search, settings
listdata-empty(値なし)
rootdata-empty(値なし)
rootdata-stateopen

Examples

Closed dialog

role="dialog" の Command を closed(hidden)状態で組み立てる最小例です。

role="dialog" の Command を closed(hidden)状態で組み立てる最小例です。

利用者スタイルの当て方

data-scope / data-part / data-selected / data-disabled / data-empty / hidden 属性セレクタで自前 CSS を当てる最小例です。

利用者が data-scope / data-part / data-selected / data-disabled / data-empty / hidden 属性セレクタで自前 CSS を当てる最小例です(本 Demo には適用されません)。

CSS
[data-scope="command"][data-part="root"][data-empty] {
  min-height: 4rem;
}
[data-scope="command"][data-part="item"][data-selected] {
  background: #eef;
}
[data-scope="command"][data-part="item"][data-disabled] {
  opacity: 0.5;
}
[data-scope="command"][data-part="dialog"][hidden] {
  display: none;
}

Accessibility

WAI-ARIA

AttributeDescription
role="combobox" / aria-autocomplete="list"input パーツに固定付与する。ARIA 1.2 combobox パターンを再利用する(combobox.rs との共通契約)。
aria-controlsinput パーツに必須引数として付与する(list_id、Option opt-in にしない)。
aria-activedescendantinput パーツに Some のときのみ付与する。選択中 item の id を指す(ハイライト中の行ではない、command.rs参照)。
role="listbox" / aria-labellist パーツに固定付与する。aria-label は必須引数のため常にアクセシブルネームを持つ。
role="option" / aria-selecteditem パーツに固定付与する。
role="dialog" / aria-modal="true"dialog パーツに固定付与する。tabindex="-1" も固定付与し、プログラム的フォーカスのみを許可する。
role="group" / aria-labelledbygroup パーツに labelledby が Some のときのみ付与する。group_heading の id と対にする。
role="separator" / aria-orientation="horizontal"separator パーツに固定付与する。