カスタムセレクトとコンボボックスシステム は何をしますか?
目的
カスタムセレクト・コンボボックスシステムは、ドロップダウンオプション、オートコンプリート検索セレクター(コンボボックス)、マルチセレクトトークン入力を設計・構造化するための体系的な方法論を提供します。
標準のHTML <select>要素は、ブラウザ間で一貫したスタイル適用が非常に難しく、個々の選択肢内にリッチなレイアウト構成(説明文、アイコン、バッジ、サブグリッドなど)をサポートできません。しかし、カスタムドロップダウンは、壊滅的なアクセシビリティ障害、キーボードトラップ、ユーザビリティバグの頻繁な原因となっています。このスキルは、デザイン、空間、インタラクションの標準を確立し、カスタムセレクトコンポーネントが視覚的に一貫性があり、高い応答性を持ち、完全にアクセシブル(WCAG 2.2 AA準拠)であることを保証します。
ユースケース
このシステムは以下の設計に適用します。
- リッチコンテンツドロップダウン: 視覚的なインジケーター、サブタイトル、補助メタデータ、ステータスバッジが必要な選択項目(例:国旗アイコン付きの国セレクター、ワークスペーススイッチャー、アカウントプロフィール)。
- 検索可能セレクター(コンボボックス): 10以上のオプションがあり、ユーザーがインライン検索入力で選択肢をフィルタリングできる必要があるドロップダウン(例:長い都道府県リスト、タグ選択)。
- マルチセレクトトークンフィールド: 複数選択が許可され、選択されたアイテムがトリガーコンテナ内またはその隣に、閉じることができるバッジ/チップとして表示されるフィールド。
- 動的設定フィルター: リッチなレイアウト配置と即時のコンテキストフィードバックが必要な高密度フィルターコントロール(例:Eコマースやデータダッシュボードのサイドバー)。
使用すべきでない場合
このシステムを以下の場合には適用しないでください。
- オプション数が少ない場合(2~5個):
segmented-control-systemまたは標準のグループ化されたラジオボタンを使用します。これにより、オプションを余分なクリックの背後に隠すことを避け、認知負荷を低減します。 - グローバルページナビゲーション: ドロップダウンアイテムをクリックするとすぐに別のページやサイトマップノードにリダイレクトされる場合は、
site-navigation-systemまたはネストされたドロップダウンメニューを使用します。セレクト入力はプロパティを編集するためのセマンティックなフォームフィールドであり、サイトマップを移動するためのものではありません。 - 標準のスタイル未適用フォーム: 一般的で優先度が低い、またはユーティリティフォーム(基本的な問い合わせフォームなど)の場合は、デフォルトでネイティブブラウザの
<select>入力を使用します。ネイティブドロップダウンは、完璧で無料のモバイルレスポンシブ対応とネイティブのスクリーンリーダーサポートを提供します。 - フルスクリーンコマンドパレット: 単一のフォーム値を選択するのではなく、アプリ全体のページとアクションを検索することが目的の場合は、
command-palette-systemを使用します。
入力
カスタムセレクトまたはコンボボックスを設計する前に、以下の要件を収集します。
- オプションの数と密度: いくつのオプションが存在するか(例:5、50、500以上)?最大文字長は?
- セレクトタイプ: シングルセレクト vs マルチセレクト?静的リスト vs 非同期的にフィルタリングされるクエリリスト(コンボボックス)?
- データの豊富さ: オプションに補助的な視覚要素(アイコン、アバター、フラグ、カラーチップ)や補足テキスト(サブラベル、価格変更、アクティブユーザー数)が必要か?
- レイアウトコンテキスト: これは高密度のサイドバー、広々としたランディングページ、オーバーレイモーダル、それとも永続的な設定ダッシュボードに配置されるか?
- ブランドトークン: スペーシングスケール(
fluid-spacing-system)、タイポグラフィスケール(fluid-typography-system)、フォーカスリング(focus-indicator-design-system)、エレベーションシャドウスケール(elevation-and-depth-system)。
出力
このシステムは以下の設計成果物を生成します。
- アナトミー仕様: トリガー と ドロップダウンパネル の両方について、スペーシング、配置、アイコン、テキスト切り詰めルール、境界線/背景レイヤーを示す詳細な青写真。
- 状態&インタラクティブマトリックス: ホバー、アクティブ/オープン、選択、フォーカス、無効、バリデーションエラー状態の定義された視覚スタイル。
- レスポンシブ適応モデル: デスクトップドロップダウンがモバイルビューポートでどのように変換されるか(例:ボトムドロワー/シートへの変換、またはネイティブフォールバックオーバーレイ)を示す構造仕様。
- アクセシビリティマップ(WAI-ARIA&キーボード): 開発者に引き渡すための、正確なロール、ライブリージョン宣言、フォーカストラッキング状態、キーマッピング動作。
ワークフロー
1. コンポーネントアナトミーを構造化する
完全なカスタムセレクトシステムは、2つの主要な空間レイヤーで構成されます。
A. トリガー(フィールド)
- コンテナ: 隣接するフォーム入力と高さを合わせます(通常、タッチターゲットとして40px~48px)。ニュートラルなアウトライン(ページ背景に対するコントラスト3:1)と定義されたパディング(通常
12px 16px)を使用します。 - 値/プレースホルダースロット: 左側に配置。非アクティブなテキストはプレースホルダーを表します(フィールド背景に対するコントラスト >= 4.5:1)。選択されたテキストは、プライマリニュートラルのウェイトでスタイルされます。
- 視覚的アフォーダンス(矢印シェブロン): 右端に配置。折りたたみ可能なコンテンツを示すために、下向きのシェブロンを使用します。メニューがアクティブなときは、シェブロンを180度回転させます。
- 選択済みバッジ(マルチセレクトのみ): コンパクトなインラインチップで、個別の閉じる(x)コントロールを持ち、優雅に折り返すか、カウント修飾子で切り詰めます(例:「+3 その他」)。
B. ドロップダウンパネル(メニュー)
- オーバーレイコンテナ: 高いZ軸レベル(
elevation-and-depth-systemレベル3/4)に配置。デフォルトではトリガーの下に、ビューポート端が下部スペースを制限する場合はトリガーの上にレンダリングされます。明確なシャドウ(例:ソフトブラーのあるbox-shadow)を使用して、背景ページから浮き上がらせます。 - スクロールコンテナ: パネルがページからはみ出さないように、最大高さ制約(通常
240px~320px/ 5~8アイテム)を設定します。長いリストには、スクロールバーシフトを防ぐための可視スクロールトラックを使用します。 - 検索入力(コンボボックスのみ): ドロップダウンパネルの上部に固定されたスティッキー検索入力で、メニューアクティブ化時に永続的にフォーカスを持ちます。
C. オプションアイテム(選択肢)
- レイアウト: 左側の視覚アセット、中央のプライマリテキスト(リッチオプションの場合はサブタイトル)、右側の選択状態インジケーター(チェックマークなど)で構成される水平フレックスレイアウト。
- 安全なパディング: 最小垂直パディング
8px、トリガーの水平パディングに合わせた水平パディング(12px~16px)。
+------------------------------------------+
| 国を選択 [v] | <-- トリガー(閉じている)
+------------------------------------------+
+------------------------------------------+
| [Q] 国を検索... | <-- スティッキー検索入力
+------------------------------------------+
| [x] カナダ | <-- オプション(選択済み&フォーカス)
| ISO: CA | +1 国番号 |
|------------------------------------------|
| [ ] ドイツ | <-- オプション(デフォルト)
| ISO: DE | +49 国番号 |
+------------------------------------------+
2. 状態とフィードバックマトリックスを策定する
コンポーネントのすべてのライフサイクル状態に対して、明確で曖昧さのないスタイルを設計します。
- デフォルト状態: トリガーは明確なアウトライン(ページ背景に対する最小コントラスト3:1)と明確なテキストラベル(最小コントラスト4.5:1)を使用します。
- ホバー状態: トリガー(例:低コントラストのグレー)とオプション行に微妙な背景色の変化をつけて、インタラクティブ機能を示します。カーソルは
pointerに設定します。 - フォーカス状態: アクティブな要素を囲む非常に視認性の高いフォーカスリング。コンボボックスの場合、リストが開いている間はフォーカスは検索入力に置かれますが、ハイライトされたリストオプションには視覚的なフォーカス処理(例:背景色の変化またはアクティブアウトライン)を使用します。
- アクティブ/展開状態: シェブロンが回転し、トリガーのアウトラインの色が変わり(例:プライマリブランドカラー)、ドロップダウンパネルがスムーズな高さと不透明度のトランジション(150ms~250ms)で表示されます。
- 選択状態: 選択されたときにオプション行が視覚的に変化します。右端に高コントラストのチェックマークアイコンと微妙な背景塗りつぶしを使用します。選択を示すために色だけに依存しないでください。
- 無効状態: 視覚的な不透明度を40%~50%に低減。カーソルは
not-allowedインジケーターになり、要素はタブインデックスからスキップされます。 - エラー/無効状態: トリガーのアウトラインがバリデーションエラー色(通常は高コントラストの赤、>= 3.1コントラスト)に変わり、入力の下にエラーメッセージとエラーアイコンが表示されます。
3. 空間と配置のルールを確立する
レイアウトの衝突と累積レイアウトシフト(CLS)を回避するには:
- 動的配置(フリップ動作): ビューポートの境界を計算します。ドロップダウンコンテナがビューポート下部の折り返しに近い場合は、配置を反転してトリガーの上にスライドアップするようにします。
- 幅の調整: ドロップダウンパネルはトリガーの左右の端と正確に一致するか、視覚的な不安定さを防ぐためにトリガーと一致する定義済みの最小幅を持たせる必要があります。
- オーバーレイの分離: エレベーションシステムのレベル3(スティッキー/フローティングUI)またはレベル4(オーバーレイとダイアログ)に一致するCSS
z-indexスタックを使用します。パネルが常に隣接するフォーム要素、背景、レイアウトカードの上にレンダリングされるようにします。
4. レスポンシブ&モバイル適応を設計する
マルチカラムまたはワイドなデスクトップドロップダウンメニューを小さなモバイルビューポートに強制しないでください。以下の適応レイアウトルールを適用します。
パターンA: モバイルボトムシート(リッチオプション推奨)
画面サイズが 640px 未満(または標準のタブレットブレークポイント)の場合、カスタムドロップダウンパネルをスライドする ボトムシート に変換します。
- トリガー: トリガーをタップすると、全幅のボトムシートオーバーレイが開きます。
- スクリム: 半透明の暗い背景(40%~60%の不透明度)がメインコンテンツを覆い、背景要素を非インタラクティブにします。
- ヘッダー: シートには、明確なタイトルと右上隅にある大きなタッチアクセス可能な「閉じる」(x)ボタンを備えたスティッキーヘッダーが含まれます。
- サムリーチャビリティ: オプション行は画面幅全体を占有し、タッチターゲットの高さが増加(最小48px、推奨56px)して、指でのタップ選択が容易になります。
パターンB: ネイティブフォールバック(シンプルリスト推奨)
モバイルビューポートでは、カスタムマークアップをスクリーンリーダーと視覚DOMから完全に非表示にし、視覚的には非表示で、レイヤースタックされたネイティブ <select> 要素に置き換えます。
- 仕組み:
opacity: 0でスタイル設定された標準の<select>をカスタムトリガーの上に直接配置します。 - 結果: ユーザーはカスタムブランドのトリガーを目にしますが、タップするとネイティブOSの選択ホイール(iOS PickerまたはAndroid Dialog)がアクティブになります。これにより、比類のないネイティブパフォーマンスとローカルアクセシビリティが提供されます。
5. スクリーンリーダー&キーボードアーキテクチャを定義する
カスタムセレクト要素は、完全な支援技術をサポートする必要があります。引き渡しのために、この正確な動作を指定します。
ARIAマッピングとセマンティクス
- トリガーボタン:
role="combobox"、aria-haspopup="listbox"、aria-expanded="true/false"、aria-controls="listbox-id"を持つ必要があります。 - ドロップダウンパネル:
role="listbox"を持ち、トリガーのIDでラベル付けされます(aria-labelledby="trigger-id")。 - オプションアイテム:
role="option"を持つ必要があります。現在選択されているアイテムはaria-selected="true"を持ち、他のアイテムはaria-selected="false"を持つ必要があります。 - フォーカス管理: オートコンプリートコンボボックスの場合、検索入力は
aria-autocomplete="list"を持つ必要があります。入力でaria-activedescendant="option-id"を使用して、ユーザーが上下の矢印キーを移動する際に視覚的にハイライトされたオプションを追跡します。 - ライブアナウンス:
aria-live="polite"または専用のスクリーンリーダーアナウンサー要素を使用して、選択状態の変更やカウントの更新をブロードキャストします(例:「5個のオプションが見つかりました。矢印キーで移動してください。」)。
キーボードインタラクションテーブル
仕様書では、これらの正確なホットキーマッピングを必須とします。
| アクション | キー押下 | 期待される動作 |
|---|---|---|
| メニューを開く | Space または Enter または ArrowDown | ドロップダウンパネルを開き、最初のオプション(または検索)にフォーカスを置きます。 |
| メニューを閉じる | Escape または Tab | パネルを閉じ、キーボードフォーカスをトリガーに戻します。 |
| オプションを移動 | ArrowDown / ArrowUp | アクティブなハイライト状態を次のまたは前のオプション行に移動します。 |
| オプションを選択 | Space または Enter | ハイライトされたオプションを選択し、値を更新し、パネルを閉じます。 |
| 最初/最後の項目 | Home / End | アクティブなハイライトをオプションリストの先頭または末尾に移動します。 |
| ジャンプ検索 | 任意の英数字キー | 静的な場合、フォーカスはその文字で始まる最初のオプションにすぐにジャンプします。 |
決定ルール
カスタムセレクトオプション決定木
全部でいくつのオプションがありますか?
├── 2~5個のオプション ─────────> セグメントコントロールまたはグループ化されたラジオボタンを使用
├── 6~10個のオプション ────────> カスタムセレクトを使用(単一カラム、検索入力なし)
└── 10個以上のオプション ────> コンボボックスを使用(検索入力統合型カスタムセレクト)
正しい選択パターンの選択
| 要件 | 標準セレクトを使用 | 検索可能コンボボックスを使用 | マルチセレクトトークンを使用 |
|---|---|---|---|
| 選択制限 | 単一値のみ | 単一値のみ | 複数値を同時に |
| オプション規模 | 6~15アイテム | 15~100+アイテム | 5~50アイテム |
| 摩擦タイプ | 低い探索 | 素早いターゲット取得が必要 | 累積的な組み立て |
| オプションレイアウト | シンプルなテキスト行 | シンプルまたはリッチリスト行 | 折り返しレイアウトのチップ/トークン |
制約事項
- フォーカス保持:
Escapeまたは外部クリックでドロップダウンを閉じる場合、フォーカスが失われたり、最上位のサイトマップレベルにリセットされてはなりません。プログラムでトリガー要素に戻る必要があります。 - フォーカスの可視性(WCAG 2.2 SC 2.4.11): トリガーまたはアクティブオプションのフォーカスインジケーターは、スティッキーページヘッダー、フローティングボトムバー、重なり合うオーバーレイによって隠されたり不明瞭になったりしてはなりません。
- タッチターゲット(WCAG 2.2 SC 2.5.8): すべてのオプション行とトリガー要素は、最小クリック可能サイズ
24x24pxを持ち、40px~48pxの高さがデフォルトのレイアウト要件であり、モバイルデバイスでのタッチの重なりを避けます。 - **色のコントラスト(WCAG...