はじめに 🌟
Fluent UI 2 は、Microsoft のデザインシステムです。コンポーネントの見た目だけではなく、操作の意味、情報設計、アクセシビリティまで含めてガイドされているのが特徴です。今回扱う Tag は、まさにその思想がよく出るコンポーネントです。✨
公式の説明では、Tag は「ユーザーが選んだ値(メール受信者、カテゴリなど)を表すもの」で、変更や削除ができることを伝える視覚パターンです。一方、変更できないシステム生成情報は Badge を使うべきだと明記されています。ここが Tag と Badge の最初の分岐点です。🔍
今回のゴール 🎯
- ✅ Fluent UI 2 とは何かを Tag 文脈で整理する
- ✅ Tag と Badge のユースケースと使い方の違いを明確化する
- ✅ Fluent UI Blazor 5 での実装方針(Tag 同名コンポーネントがない想定)を示す
- ✅ Tag のガイダンス・種類・動作・レイアウト・アクセシビリティ・コンテンツを体系化する
Fluent UI 2 シリーズ記事の紹介(これまでの全記事)
以下は、これまで公開してきた Fluent UI 2 シリーズ記事です(重複タイトルは統合)。📚
- Fluent UI 2 で始めるアクセシビリティ実装 — キーボード操作・支援技術・WCAG 2.1 の実践ガイド
- Fluent UI 2 の Accordion を理解する — 情報設計・アクセシビリティ・React 実装
- Fluent UI 2 の Avatar を整理しつつ Fluent UI Blazor 5 でどう実装するか
- Fluent UI 2 の Badge を理解する — Fluent UI Blazor 5 との比較と実装ポイント
- Fluent UI 2 の Breadcrumb を理解する — Fluent UI Blazor 5 との対応とアクセシビリティ
- Fluent UI 2 の Button を理解する — 種類・レイアウト・アクセシビリティ・Blazor 5 比較
- Fluent UI 2 の Card を理解する — React と Fluent UI Blazor の違い
- Fluent UI 2 の Checkbox を理解する — React と Fluent UI Blazor v5 の違い
- Fluent UI 2 の Combobox を理解する — Fluent UI Blazor 5 との比較と使い分け
- Fluent UI 2 の Dialog を理解する — React と Fluent UI Blazor 5 の違いと使い分け
- Fluent UI 2 の Divider を理解する — Fluent UI Blazor 5 との比較
- Fluent UI 2 の Drawer を理解する — Tooltip / Popover / Dialog との使い分けと Fluent UI Blazor 5 比較
- Fluent UI 2 の Dropdown を理解する — Fluent UI Blazor 5 の近縁コンポーネント比較とアクセシビリティ
- Fluent UI 2 の Field を理解する — Fluent UI Blazor 5 と比較する入力設計の基礎
- Fluent UI 2 の Icon を理解する — Fluent UI Blazor の FluentIcon 比較とアクセシビリティ
- Fluent UI 2 の Image を理解する — Fluent UI Blazor 5 と比較しながらレイアウトとアクセシビリティを整理する
- Fluent UI 2 の Input を理解する — Textarea・Fluent UI Blazor TextInput / Number 比較とアクセシビリティ
- Fluent UI 2 の Label を理解する — Fluent UI Blazor 5 と比較するラベル設計の基礎
- Fluent UI 2 の Link を理解する — Fluent UI Blazor 5 と比較するリンク設計とアクセシビリティ
- Fluent UI 2 の Menu を理解する — Fluent UI Blazor 5 と比較するガイダンス・動作・アクセシビリティ
- Fluent UI 2 の MessageBar を理解する — Fluent UI Blazor 5 と比較する機能・使用方法・アクセシビリティ
- Fluent UI 2 の Nav を理解する — ガイダンス・動作・レイアウト・アクセシビリティと Fluent UI Blazor 5 比較
- Fluent UI 2 の Persona を理解する — ガイダンス・レイアウト・アクセシビリティ・Fluent UI Blazor 5 比較
- Fluent UI 2 の Popover を理解する — Fluent UI Blazor 5 との比較と Tooltip / Dialog の使い分け
- Fluent UI 2 の Progress Bar を理解する — Fluent UI Blazor 5 比較と Skeleton 使い分け・アクセシビリティ
- Fluent UI 2 の Radio Group を理解する — Fluent UI Blazor 5 との比較・使い分け・アクセシビリティ
- Fluent UI 2 の Rating を理解する — Fluent UI Blazor 5 と比較する評価 UI の設計とアクセシビリティ
- Fluent UI 2 の Searchbox を理解する — Fluent UI Blazor 5 との比較とアクセシビリティ・コンテンツ設計
- Fluent UI 2 の Select を理解する — Dropdown / Combobox / Field との使い分けと Fluent UI Blazor 5 比較
- Fluent UI 2 の Skeleton を理解する — ProgressBar・Spinner との使い分けと Fluent UI Blazor 5 比較
- Fluent UI 2 の Slider を理解する — Input/Number 比較と Fluent UI Blazor 5 との違い、アクセシビリティとコンテンツ設計
- Fluent UI 2 の Spin button を理解する — Slider との違い、Fluent UI Blazor 5 の Number / StepButtons 比較とアクセシビリティ
- Fluent UI 2 の Spinner を理解する — Progress Bar / Skeleton との使い分けと Fluent UI Blazor 5 比較
- Fluent UI 2 の Switch を理解する — Checkbox との違い、即時適用、アクセシビリティ実装
- Fluent UI 2 の Tablist を理解する — Link / Button との違い、Fluent UI Blazor Tabs 比較、アクセシビリティとコンテンツ設計
- Fluent UI 2 のアクセシビリティを色から読む ─ WCAG 2.1 と対比しながら整理する
Tag と Badge の違い(ユースケースと使用法)
公式ガイドの意図を短く言うと、次の通りです。
- Tag: ユーザーが選んだ値を表し、変更・削除できる前提
- Badge: 関連要素の状態を示す視覚インジケーターで、変更不可情報に向く
| 観点 | Tag | Badge |
|---|---|---|
| 🧭 目的 | 選択値の表現・編集導線 | 状態/説明の表示 |
| 👤 主体 | ユーザー操作起点 | システム状態起点 |
| 🗑️ 削除 | dismiss あり(任意) | 基本なし |
| 🧩 情報量 | オブジェクト名・選択値 | 1〜2語の短い状態語 |
| ♿ 設計要点 | 操作可能性と文脈理解 | 色だけに頼らず意味を伝える |
使い分けの実例
- メール受信者、カテゴリ、検索フィルターの「選択済み」は Tag が自然です。
- 未読件数、オンライン状態、警告状態の表示は Badge が自然です。
- 迷ったときは「これはユーザーが外せる/変えられるか?」で判断するとぶれません。🧠
Fluent UI Blazor 5 と Fluent UI 2 の Badge 比較
Fluent UI 2 側では Badge は「状態表示」の概念として整理されています。Blazor 側では、同じ役割を FluentBadge / FluentCounterBadge / FluentPresenceBadge で表現できます。
| 項目 | Fluent UI 2 Badge | Fluent UI Blazor 5 |
|---|---|---|
| 位置づけ | 状態・説明の visual indicator |
FluentBadge 系で実装可能 |
| コンテンツ | 短く説明的な語(1〜2語) | 同様。長文は避ける |
| 色の使い方 | 意図的に使い、次の行動を示す | 色 + テキストで意味補強 |
| a11y | アイコンのみなら aria-label 必須 | 同様。支援技術向けラベルを明示 |
Fluent UI Blazor 5 で Tag 相当をどう提供するか
前提として、Blazor 側に Tag 同名コンポーネントがない想定では、機能を合成して提供するのが現実的です。
- 見た目は
FluentBadge(または丸みを持つコンテナ)でチップ化する - 削除操作は
FluentButton(stealth)を付与する - 複数タグの構造化は、一例として
role="list"+role="listitem"を採用する - 追加/削除時はライブリージョンなどで結果を通知する
<div role="list" aria-label="選択中のカテゴリ">
@foreach (var item in SelectedCategories)
{
<div role="listitem" class="tag-chip">
<FluentBadge Appearance="Appearance.Outline" Color="Color.Neutral">
@item
</FluentBadge>
<FluentButton Appearance="Appearance.Stealth"
AriaLabel="@($"{item} を削除")"
@onclick="() => RemoveCategory(item)">
×
</FluentButton>
</div>
}
</div>
Tag 相当では「見た目」より「状態遷移」と「読み上げ」を先に設計すると失敗しにくいです。
Fluent UI 2 Tag のガイダンス
Tag は「ユーザーが選んだ値」を表現し、必要なら戻せるようにするための UI です。公式の要点は次の通りです。
- 変更不可のシステムデータ表示には Badge を使う
- Tag は値の変更可能性を視覚的に示す
- 人が作業中に値を外せる/見直せることが重要
Tag の種類(Types)
Tag
情報提供中心で、できる操作は dismissal のみです。
Interaction tag
dismiss 以外に 1 つの主要アクションを持てます。例えばユーザー名 Tag を押して詳細ポップオーバーを開く、といった使い方です。
Tag の動作(Behavior)
Dismissal
- 両タイプとも dismiss は任意で有効化できます。
- dismiss を有効化すると、ユーザーが選択を取り消せます。
- 非 dismissible Tag は「今は編集不可」を示す用途で使えます。
Interaction tag の primary / secondary action
- primary action は Tag が表すオブジェクトと直接関係する操作に限定します。
- secondary action は常に dismiss です。
Reflow と Overflow
- 既定では Tag はコンテナに収まらないと次行へ reflow します。
-
+n表示の overflow Tag を置く場合、その Tag は interaction tag である必要があります。 - 編集しやすさが重要なら、overflow で隠しすぎず、wrap して全体を見せる設計が有効です。
Tag のレイアウト(Layout)
公式では最小スペーシングが明示されています。
- Extra small 間: 4px
- Small 間: 6px
- Medium 間: 8px
同サイズ帯で密度をそろえ、周辺余白は全体レイアウトガイドに合わせるのが基本です。📐
Tag のアクセシビリティ(最重要)♿
Tag は小さな UI ですが、アクセシビリティの難所です。特に重要なのは次の 4 点です。
1. Interaction state を正しく扱う
- 通常 Tag は静的要素で interaction state を持ちません。
- dismiss 有効時はホバー/フォーカス状態が有効になります。
- interaction tag は常に操作可能状態として扱われます。
2. フォーカス順と操作結果を明確にする
- キーボードで到達できる順序を視覚順と一致させます。
- 削除後にフォーカスが迷子にならないよう、次の Tag か入力に戻します。
- 削除時は「何が削除されたか」を読み上げ可能にします。
3. 色やアイコンだけで意味を完結させない
- 形状/テキスト/aria-label を併用して意味を伝えます。
- アイコンのみ表示なら代替テキストは必須です。
4. 文字列の切り詰めをしない
公式に「Tag content を truncation しない」とあります。Tag の意味が瞬時に伝わらなくなるためです。ここは実装時に特に落としやすいポイントです。
5. 状態遷移のアクセシビリティを実装で担保する(Blazor)
Tag 相当 UI では、見た目より「状態遷移をどう伝えるか」が重要です。私は次の 4 点を必須チェックにしています。
-
操作対象の名前:
aria-label="東京 を削除"のように、対象名を含める -
結果通知:
aria-live="polite"で追加/削除結果を読み上げる - フォーカス復帰: 削除後に次の Tag、なければ入力欄へ戻す
- キーボード操作(実装推奨): Tab 到達、Enter/Space 実行、Delete/Backspace 削除のようにアプリ内で一貫した操作体系を定義する
<div role="list" aria-label="選択中のカテゴリ">
@foreach (var item in SelectedCategories)
{
<div role="listitem" class="tag-chip">
<FluentBadge Appearance="Appearance.Outline" Color="Color.Neutral">
@item
</FluentBadge>
<FluentButton Appearance="Appearance.Stealth"
AriaLabel="@($"{item} を削除")"
@onclick="() => RemoveCategory(item)">
×
</FluentButton>
</div>
}
</div>
<div class="sr-only" aria-live="polite">@LiveMessage</div>
private string LiveMessage = string.Empty;
private async Task RemoveCategory(string item)
{
SelectedCategories.Remove(item);
LiveMessage = $"{item} を削除しました";
// 次のフォーカス先(次のTag or 入力欄)へ移す実装をここで行います。
await Task.Yield();
}
Tag で最も避けたいのは「見えているラベルは短いが、何を指すか分からない」状態です。
読み上げ・フォーカス・文言の 3 点をセットで設計してください。
Tag のコンテンツ(最重要)📝
公式のコンテンツ指針は、実装者にとって非常に重要です。
Tag text and validation
- Tag には最低限テキストが必要です。
- 文字列を UI 側で勝手に作るのではなく、通常はバックエンドの一致データを使います。
- 一致候補がない入力(外部メールアドレスなど)は、入力値をそのまま Tag に表示できます。
Show the most important info
- primary / secondary content を持てますが、関連情報だけを表示します。
- 例として、エイリアス入力で検索した場合でも、Tag には本来表示すべき名前を出すべきです。
- スキャンしづらくなる冗長情報は避けます。
実務向けチェック
| チェック項目 | OK の基準 |
|---|---|
| 🔤 文言の一貫性 | 同じ概念を同じ語で表記 |
| 🧠 意味の即時理解 | 単体で何の値か分かる |
| 🧹 情報量 | 重要情報のみで短く保つ |
| ♿ 支援技術対応 | aria-label と結果通知がある |
おわりに
Tag は見た目が小さいぶん、設計意図が曖昧になりやすいコンポーネントです。ですが、Fluent UI 2 のガイドを丁寧に読むと、Tag と Badge の境界、操作性、アクセシビリティ、コンテンツ設計まで一貫して整理できます。🚀
特に今回のポイントは、Tag は「選択値の編集可能性」を伝える UIであり、Badge は「状態表示」中心の UIだという点です。Blazor 5 で Tag 同名コンポーネントがない場合でも、役割を分解して合成すれば、十分に Fluent UI 2 の意図を再現できます。