フィルターボタンFilterButtonExperimental
条件の選択状態をボタン上のバッジとポップオーバーで扱うフィルター操作です。
プレビュー
状態とバリエーション
フィルターボタンの見た目は、見た目の種類ではなく、未選択、メニュー表示中、選択済みという実行時の状態から決まります。プロパティの前に、状態ごとの見え方と使い分けを確認します。
default
フィルター
選択がなく、メニューも閉じている通常状態。
popover
フィルター
メニューを開いて、選択候補を確認している状態。
selected
フィルター2
選択件数のバッジを持つ、条件適用済みの状態。
未選択から選択する
未選択状態からメニューを開き、複数条件を選択します。選択されると件数バッジが表示されます。
選択済み
選択値がある時は選択済み状態になり、ボタン上に件数バッジを表示します。
カスタムメニュー
内容を差し替えると、色、タグ、容量範囲など、標準リスト以外のフィルター UI を配置できます。
プロパティ
表は横にスクロールできます
| プロパティ | 型 | 初期値 | 説明 |
|---|---|---|---|
| title | string | "Filter" | ボタンに表示するラベルです。 |
| icon | ReactNode | - | 任意の先頭アイコンです。未指定時はフィルターアイコンを表示します。 |
| options | FilterOption[] | - | 標準リスト表示に使う選択肢です。 |
| selectedValues | Set<string> | - | 現在選択されている値です。件数バッジと選択済み状態に使われます。 |
| onFilterChange | (values: Set<string>) => void | - | 選択値が変わった時に呼ばれます。 |
| clearLabel | string | "Clear filters" | メニュー内のクリアアクションのラベルです。 |
| selectedLabel | (count: number) => string | - | 件数バッジの読み上げ用ラベルを生成します。 |
| contentClassName | string | - | 開いたメニューに追加するスタイル用クラスです。 |
| contentAlign | "start" | "center" | "end" | "start" | ポップオーバーの横位置です。 |
| portalContainer | HTMLElement | null | - | 擬似ブラウザや入れ子の表示領域に閉じ込めたい時の表示先です。 |
| children | ReactNode | - | 色、タグ、評価など、標準リスト以外の独自フィルター UI です。 |
使い方
import { FilterButton } from "@gunjo/ui";
import { useState } from "react";
const options = [
{ label: "未対応", value: "todo" },
{ label: "進行中", value: "doing" },
{ label: "完了", value: "done" },
];
export function StatusFilterButton() {
const [selected, setSelected] = useState<Set<string>>(new Set());
return (
<FilterButton
title="ステータス"
options={options}
selectedValues={selected}
onFilterChange={setSelected}
clearLabel="クリア"
selectedLabel={(count) => count + "件選択中"}
/>
);
}設計の判断
- 絞り込みの有無をボタン自身が示す。何も選ばれていないときは破線の枠、開いているあいだは淡い色、選ばれているときは実線の枠と淡い色、と3つの見た目を持ちます。資料の「重要度と視覚的重みを一致させる」を、優先度ではなく状態に当てて使った形です。
- 件数の場所を先に空けておく。選択が0件のときも件数のバッジは場所を取ったまま隠れ(
invisible)、読み上げからは外れます。0件で消してしまうと、1つ選んだ瞬間にボタンの幅が変わって、隣のボタンが動くためです。 - 中身を丸ごと差し替えられる。
childrenを渡すと、既定の選択一覧の代わりに任意の中身を出せます(日付の範囲・数値の幅など)。絞り込みの形は画面ごとに違うので、部品にしたのはボタンと吹き出しの枠だけです。
一般のボタンの設計は UIXHERO の「ボタン」にあります。
いつ・なぜ使うか(UIXHERO)
「いつ・なぜ使うか」の判断は、姉妹サイト UIXHERO の記事で解説しています。