1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに 🌟

Fluent UI 2 の Select は、フォームで使う「選ぶ」コンポーネントの中でもっともシンプルな部品です。
ブラウザーネイティブのスタイルで描画されるため、モバイルとの相性がよく、アクセシビリティ的にも安定しています。

この記事では、まず Fluent UI 2 とはどういうものかを整理し、これまでのシリーズを振り返ります。
そのうえで、Fluent UI 2 の Select に焦点を当て、同じ「選ぶ系」コンポーネントである Dropdown / Combobox / Field との使い分けを整理します。
さらに、Fluent UI Blazor 5 の FluentSelect との違い、Blazor 側の Autocomplete を含む近縁コンポーネントの比較も行います。

参考にした公式ページはこちらです。

今回のゴール ✅

  • ✅ Fluent UI 2 の Select の役割と適用場面を理解する
  • Dropdown / Combobox / Field との違いと使い分けを整理する
  • ✅ Fluent UI Blazor 5 の FluentSelect との実装差を把握する
  • ✅ Blazor 5 の Autocomplete を含む近縁コンポーネントを比較する
  • ✅ アクセシビリティとコンテンツ設計の要点を押さえる

Fluent UI 2 とは

Fluent UI 2 は、Microsoft の Fluent 2 デザインシステムを実装に落とし込むための UI コンポーネント群です。
単なる見た目のそろえ方ではなく、操作の一貫性・情報の意味づけ・支援技術での理解しやすさまでをまとめて設計するのが特徴です。

Select はこの中でも「標準的なフォーム選択」を担う部品です。
一見すれば普通のプルダウンですが、いつ使うか・なぜ使うかを公式ガイドが明確に定義しています。
それが Dropdown / Combobox との判断基準につながります。

これまでの Fluent UI 2 シリーズ一覧 🧭

本記事までのシリーズは次のとおりです。

テーマ 記事
🔘 Button Fluent UI 2 の Button を理解する
🧩 Accordion Fluent UI 2 の Accordion を理解する
🗂️ Breadcrumb Fluent UI 2 の Breadcrumb を理解する
🪪 Card Fluent UI 2 の Card を理解する
☑️ Checkbox Fluent UI 2 の Checkbox を理解する
🏷️ Badge Fluent UI 2 の Badge を理解する
👤 Avatar Fluent UI 2 の Avatar を整理しつつ Fluent UI Blazor 5 でどう実装するか
🗨️ Dialog Fluent UI 2 の Dialog を理解する
⌨️ Combobox Fluent UI 2 の Combobox を理解する
♿ アクセシビリティ実装 Fluent UI 2 で始めるアクセシビリティ実装
🎨 色と WCAG Fluent UI 2 のアクセシビリティを色から読む
🔽 Dropdown Fluent UI 2 の Dropdown を理解する
📝 Field Fluent UI 2 の Field を理解する
🏷 Label Fluent UI 2 の Label を理解する
🔗 Link Fluent UI 2 の Link を理解する
📢 MessageBar Fluent UI 2 の MessageBar を理解する
🧭 Nav Fluent UI 2 の Nav を理解する
🍔 Menu Fluent UI 2 の Menu を理解する
🔣 Icon Fluent UI 2 の Icon を理解する
🔵 Radio Group Fluent UI 2 の Radio Group を理解する
⭐ Rating Fluent UI 2 の Rating を理解する
🖼️ Image Fluent UI 2 の Image を理解する
👥 Persona Fluent UI 2 の Persona を理解する
🔍 Searchbox Fluent UI 2 の Searchbox を理解する(公開準備中)
🪟 Popover Fluent UI 2 の Popover を理解する
➖ Divider Fluent UI 2 の Divider を理解する

今回の Select は、Dropdown / Combobox と並ぶ「選ぶ系」の中で、フォームの標準入力というポジションをはっきりと持っています。
シリーズを通して読むと、用途別に部品を選ぶ感覚が自然に身につきます。

Fluent UI 2 Select の基本

公式ガイドの要点を先にまとめます。

項目 内容
🧭 役割 リストから 1 つを選ぶ標準フォームコンポーネント
📋 選択肢数 少なくとも 4 個以上が前提
📱 向いている場面 データ送信フォーム、モバイル向け UI
🎨 スタイル ブラウザーネイティブ
🔀 代替検討 スタイルや書式を制御したいなら Dropdown
⌨️ 入力併用 自由入力や絞り込みが必要なら Combobox
📝 Field との関係 バリデーションやヘルパーテキストが必要なら Field でラップ

A select lets people choose a single option from a list of at least four options. Selects use browser native styling for the listed options.
Fluent UI 2 Select usage

Select は「とにかく選ばせる」ことに特化した、もっともシンプルな選択 UI です。
ネイティブの <select> に近い実装のため、OS やブラウザーのアクセシビリティ機能をそのまま活用できます。🖱️

デフォルト選択の動作

初回描画時は、リストの最初の選択肢がデフォルトで選択されます。
デフォルト値を変えたいときは、SelectdefaultValue を渡すか、対応する <option>selected を付けます。

import { Select } from "@fluentui/react-components";

export function PrioritySelect() {
  return (
    <Select defaultValue="medium">
      <option value="low">Low</option>
      <option value="medium">Medium</option>
      <option value="high">High</option>
    </Select>
  );
}

Dropdown / Combobox / Field との使い分け

「選ぶ系」コンポーネントはどれも似ていますが、用途とトレードオフが異なります。
先に結論を整理します。

コンポーネント 向いている場面 入力 スタイル制御 複数選択
✅ Select 標準フォーム。モバイル重視 なし ブラウザー依存 基本なし
🔽 Dropdown カスタム表示。複数選択 なし(タイプアヘッドのみ) 自由 あり
⌨️ Combobox 入力しながら絞り込む あり 自由 あり
📝 Field ラベル・検証文をまとめる土台 なし(他の入力を包む)

Select

Select はブラウザーのネイティブ <select> 要素として機能します。
このため、スタイルはブラウザー・OS に依存します。
フォームとして送信することが目的で、モバイルユーザーが多い場面に向いています。
また、ネイティブ実装のため支援技術との相性も良好です。

Dropdown

Dropdown は選択 UI をカスタムレンダリングします。
選択肢にアイコンや補足情報を含めたいとき、複数選択が必要なとき、見た目を Fluent UI のデザインで統一したいときに適しています。
ただし、モバイルでは Select より使いにくくなる場合があります。

Combobox

Combobox は入力欄と候補リストの両方を持つ複合ウィジェットです。
候補が多く、テキスト入力で絞り込みたい場面や、候補にない値の自由入力を許したい場面に向きます。
詳しくは Fluent UI 2 の Combobox を理解する を参照してください。

Field

Field はコンポーネントそのものではなく、他の入力コンポーネントを包む土台です。
SelectField でラップすることで、ラベル・ヒントテキスト・バリデーションメッセージを付けられます。
詳しくは Fluent UI 2 の Field を理解する を参照してください。

Field との組み合わせでも <option> を使います。

import { Field, Select } from "@fluentui/react-components";

export function StatusField() {
  return (
    <Field label="Status" required>
      <Select>
        <option value="open">Open</option>
        <option value="in-progress">In progress</option>
        <option value="done">Done</option>
      </Select>
    </Field>
  );
}

Fluent UI Blazor 5 の近縁コンポーネント比較

Blazor 5 には React の Select に相当する FluentSelect があります。
あわせて、React Combobox に近い FluentCombobox、入力型の FluentAutocomplete も整理しておきます。

Fluent UI Blazor 5 の選択系コンポーネント

コンポーネント 主用途 入力 候補数 アクセシビリティ
🟢 FluentSelect 標準フォーム選択(React Select 相当) なし 少〜中
🔵 FluentCombobox 入力+選択(React Combobox 相当) あり 中〜多
🟡 FluentAutocomplete テキスト検索+選択 あり 多い ⚠️(未実装部分あり)
🟣 FluentListbox 一覧から選択 なし

Blazor 5 には React の Dropdown(入力欄なしのカスタム選択 UI)に 1:1 で対応するコンポーネントはありません。
FluentCombobox は React の Combobox に近い「入力+選択」型です。
入力不要なリスト選択には FluentSelect / FluentListbox を使い分けてください。

FluentAutocomplete の位置づけ

FluentAutocomplete は候補が多い場合にとくに便利です。
OnOptionsSearch に非同期検索を実装することで、大量データも扱えます。

<FluentAutocomplete TOption="string"
                    Label="Assignee"
                    Placeholder="Search by name..."
                    OnOptionsSearch="@SearchOptions"
                    @bind-SelectedOptions="@SelectedItems" />

@code {
    IEnumerable<string> SelectedItems = [];

    private void SearchOptions(OptionsSearchEventArgs<string> e)
    {
        e.Items = AllMembers.Where(x =>
            x.Contains(e.Text, StringComparison.OrdinalIgnoreCase));
    }

    static readonly string[] AllMembers =
        ["Alice", "Bob", "Carol", "Dave", "Eve"];
}

Blazor 5 の FluentAutocomplete は公式ドキュメントに Accessibility requirements are not yet implemented と記載があります。
アクセシビリティ要件が厳しい画面では、FluentSelect / FluentCombobox を先に検討してください。

Fluent UI 2 Select と Fluent UI Blazor 5 FluentSelect の違い

両者は同じ Fluent 2 の思想を共有していますが、実装レイヤーで大きな差があります。

観点 Fluent UI 2(React) Fluent UI Blazor 5
📦 コンポーネント名 Select + Option FluentSelect<TOption, TValue>
🧩 役割 ブラウザーネイティブ選択 Fluent UI ベースのリスト選択
🎨 スタイル ブラウザー依存 Fluent UI デザイントークン
🔌 選択肢定義 ネイティブ <option> を並べる Items + OptionText / 手動 FluentOption
📐 レイアウト Field でラップ Label / LabelPosition を内包
✅ 複数選択 なし(複数は Dropdown / Combobox) Multiple="true" で有効
♿ アクセシビリティ ネイティブ <select> ベース AriaLabel で補強
📵 ReadOnly 非対応(Disabled で代替)
🔢 サイズ変更 Size (Small / Medium / Large)
🎨 外観変更 Appearance (Outline / FilledLighter / FilledDarker / Transparent)

もっとも大きな差:スタイルの扱い

React 版の Select はあえてブラウザーネイティブのスタイルを使います。
モバイルでの使いやすさを最優先にしているためです。
一方、Blazor 版の FluentSelect は Fluent UI のデザイントークンでスタイリングされており、デスクトップ UI としての見た目の統一が図られています。

複数選択の差

React の Select は単一選択のみです。複数選択が必要なら Dropdown を使います。
一方、Blazor の FluentSelectMultiple="true" で複数選択が可能です。

オプションのカスタマイズ

Blazor 版では OptionTemplateOptionTextOptionValueOptionDisabled を組み合わせることで、選択肢に豊富なカスタマイズができます。
FluentOptionSlot="@FluentSlot.Start" にアイコンやアバターを入れることもできます。

<FluentSelect TOption="string"
              TValue="string"
              Label="RGB Color"
              Placeholder="Select a color"
              @bind-Value="@Value">
    <FluentOptionString Value="ff0000">Red</FluentOptionString>
    <FluentOptionString Value="00ff00">Green</FluentOptionString>
    <FluentOptionString Value="0000ff">Blue</FluentOptionString>
</FluentSelect>

@code {
    string? Value;
}

Blazor 版の FluentSelectReadOnly に対応していません。
読み取り専用にしたい場合は Disabled="true" を使い、フォームの制御ロジックで対応してください。

ガイダンス・レイアウト・動作

いつ Select を使うか

公式ガイドでは、次の条件がそろうときに Select を選ぶよう案内しています。

  • 選択肢が 4 個以上ある
  • フォームとしてデータを送信する
  • モバイルでの使いやすさを重視する
  • 選択肢をリストから選ぶだけ(入力や絞り込みは不要)

逆に、次のどれかが必要なら代替コンポーネントを検討します。

  • 選択肢の見た目をカスタムしたい → Dropdown
  • 入力して絞り込みたい → Combobox
  • 標準的なフォーム入力としてラベル+エラーをまとめて扱いたい → Field + Select

3 つ以下の選択肢は RadioGroup を検討する

公式ガイドでは明示されていませんが、Fluent UI 全体のパターンとして、3 つ以下の選択肢では RadioGroup が推奨されます。
Select は「少なくとも 4 個」が前提です。
詳しくは Fluent UI 2 の Radio Group を理解する も参照してください。

レイアウト

SelectField でラップしてレイアウトを整えるのが基本です。
ラベルの位置は Fieldorientation で調整します(vertical がデフォルト、horizontal で横並び)。

Blazor 版では FluentSelect 自体に Label / LabelPosition / LabelWidth パラメーターがあるため、FluentField でラップしなくても使えます。

<FluentSelect Label="Language"
              LabelPosition="@LabelPosition.Before"
              LabelWidth="100px"
              Items="@Languages"
              @bind-Value="@Value" />

@code {
    static string[] Languages = ["C#", "Java", "Python", "Go"];
    string? Value;
}

動作:デフォルト選択

Select は初回描画時に最初の選択肢を自動選択します。
「何も選ばれていない」状態を表現したい場合は、空の選択肢またはプレースホルダー相当の選択肢を先頭に置きます。

<FluentSelect Label="Priority"
              Placeholder="Select a priority"
              Items="@Priorities"
              @bind-Value="@Value" />

@code {
    static string[] Priorities = ["None", "Low", "Medium", "High"];
    string? Value;
}

アクセシビリティ ♿

Select に関するアクセシビリティの要点は、ネイティブの強みを活かすことと、ラベル設計にあります。

ネイティブ <select> のアクセシビリティ上の利点

React の Select はブラウザーネイティブの <select> として描画されます。
このため、次のアクセシビリティ機能がデフォルトで有効です。

  • キーボード操作:Tab でフォーカス移動、矢印キーで選択肢を移動、Enter / Space で確定
  • スクリーンリーダー:OS ネイティブの読み上げに対応(NVDA、VoiceOver、JAWS いずれも安定)
  • モバイル支援技術:iOS VoiceOver / Android TalkBack でのスワイプ操作に対応

Blazor の FluentSelect はカスタム実装のため、ARIA ロール・状態の管理が必要になります。
AriaLabel を適切に設定することで、支援技術にコンポーネントの名前を伝えます。

<FluentSelect Label="Priority"
              AriaLabel="タスクの優先度を選択してください"
              Items="@Priorities"
              @bind-Value="@Value" />

ラベルは必ず関連付ける

Select に対して、必ず関連するラベルを付けてください。
placeholder はラベルの代わりにはなりません。
フォーカスが当たると placeholder は消えてしまうため、入力の目的を伝える情報としては不十分です。

React では Field でラップすることでラベルが自動的に htmlFor で紐付きます。
Blazor では Label パラメーターを設定するか、aria-label 相当の AriaLabel を使います。

placeholder だけで入力の目的を説明するのはアクセシビリティ上の問題です。
WCAG 2.1 達成基準 1.3.1(情報及び関係性)および 3.3.2(ラベル又は説明)に影響します。
必ず label 要素またはそれに相当する属性で補完してください。

requiredaria-required

必須フィールドを示す場合は、required / aria-required を設定します。
視覚的に * を表示するだけでなく、支援技術にも「必須」であることを伝えることが重要です。

<Field label="Country" required>
  <Select>
    <Option value="">Select a country</Option>
    <Option value="jp">Japan</Option>
    <Option value="us">United States</Option>
  </Select>
</Field>

Disabled と ReadOnly

Disabled はユーザーの操作を完全に無効にします。
支援技術から操作できないだけでなく、フォーカスも受け付けません。
「閲覧はできる、操作はできない」という状態には注意が必要です。

Blazor の FluentSelectReadOnly を正式にサポートしていません。
公式ドキュメントに「ReadOnly attribute is not supported」と明記されています。
代わりに Disabled="true" を使いますが、disabled な要素はフォームの送信値に含まれないため、別途 hidden input などで値を保持する実装が必要です。

コンテンツ ✍️

Select のコンテンツ設計は、ラベルと選択肢の文言が中心です。
Fluent UI 2 公式ガイドに明確な指針があります。

ラベル

ラベルは、何を選ぶ欄かが一目で分かる説明的な名詞句にします。
単語または短いフレーズが最適です。

良い例 避けたい例 理由
✅ Country ❌ Please select your country 長すぎる
✅ Priority ❌ Priority level selection 冗長
✅ Language ❌ Choose language ラベルに動詞は不要

選択肢の文言

公式ガイドの指針は 3 点です。

  1. 並列構造で書く(名詞なら名詞、動詞なら動詞)
  2. 先頭語の重複を避ける
  3. sentence-style capitalization(先頭語のみ大文字)
種類 コメント
❌ 重複する先頭語 Sort by date / Sort by name / Sort by priority 冗長で選びにくい
✅ 並列構造 Date / Name / Priority 短く、比較しやすい
✅ None を含む None / Open / In progress / Done 解除状態を明示
❌ 大文字乱用 Low Priority / High Priority sentence-style ではない
✅ 正しい大文字化 Low priority / High priority 先頭語のみ大文字

「None」の扱い

「何も選ばない」状態が意味を持つ場合は、None を選択肢に含めます。
これは「未選択」を明示的に表現するためのものであり、ユーザーが「選んでいない」状態を取り消せるようにします。

デフォルト選択が最初の項目になる Select では、None を先頭に置くとプレースホルダー的な役割を持たせられます。

placeholder はラベルの代わりではない

先述のとおり、placeholder はラベルの代替として使えません。
「Select a priority」のような文言を placeholder に入れるより、label でしっかり目的を伝えてください。
placeholder を使う場合は、書式の例示(例: 2024-01-01)など、補足的な情報に限ります。

実装例

React(Fluent UI 2)

import { Field, Select } from "@fluentui/react-components";

export function StatusForm() {
  return (
    <Field label="Status" required hint="Select the current status of this task.">
      <Select defaultValue="open">
        <option value="open">Open</option>
        <option value="in-progress">In progress</option>
        <option value="done">Done</option>
        <option value="cancelled">Cancelled</option>
      </Select>
    </Field>
  );
}

Blazor(Fluent UI Blazor 5)

<FluentSelect Label="Status"
              Required="true"
              Message="現在の状態を選択してください。"
              Items="@Statuses"
              @bind-Value="@Value" />

<div>Selected: @Value</div>

@code {
    static string[] Statuses = ["Open", "In progress", "Done", "Cancelled"];
    string? Value = "Open";
}

Blazor — カスタム選択肢(アイコン付き)

<FluentSelect TOption="string"
              TValue="string"
              Label="Priority"
              @bind-Value="@Value">
    <FluentOptionString Value="none">
        <FluentIcon Value="@(new Icons.Regular.Size16.Line())" Slot="@FluentSlot.Start" />
        None
    </FluentOptionString>
    <FluentOptionString Value="low">
        <FluentIcon Value="@(new Icons.Regular.Size16.ArrowDown())" Slot="@FluentSlot.Start" />
        Low
    </FluentOptionString>
    <FluentOptionString Value="high">
        <FluentIcon Value="@(new Icons.Regular.Size16.ArrowUp())" Color="Color.Error" Slot="@FluentSlot.Start" />
        High
    </FluentOptionString>
</FluentSelect>

@code {
    string? Value;
}

まとめ

Fluent UI 2 の Select を理解するうえでの要点は次のとおりです。

  1. 用途を絞る:フォームとして送信すること、モバイル互換、選択肢が 4 個以上のときが適切な使い時
  2. Dropdown / Combobox と役割を分ける:カスタム表示や複数選択は Dropdown、入力絞り込みは Combobox
  3. Field でラップしてラベルと紐づける:アクセシビリティのためにラベル関連付けは必須
  4. Blazor 版は機能が豊富:Appearance / Size / Multiple など React 版にない機能を持ち、OptionTemplate でカスタマイズも可能
  5. AutoComplete は便利だがアクセシビリティに注意FluentAutocomplete はアクセシビリティ要件未実装の部分があるため、本番での扱いは慎重に

特にアクセシビリティとコンテンツ設計は、見た目調整より先に固めておくと、後から修正するより結果的に早くなります。
Select は小さなコンポーネントですが、正しく設計することで利用者の操作負荷を大きく下げられます。🚀

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?