フィルターボタンFilterButtonExperimental

条件の選択状態をボタン上のバッジとポップオーバーで扱うフィルター操作です。

プレビュー

状態とバリエーション

フィルターボタンの見た目は、見た目の種類ではなく、未選択、メニュー表示中、選択済みという実行時の状態から決まります。プロパティの前に、状態ごとの見え方と使い分けを確認します。

default
フィルター

選択がなく、メニューも閉じている通常状態。

popover
フィルター

メニューを開いて、選択候補を確認している状態。

selected
フィルター2

選択件数のバッジを持つ、条件適用済みの状態。

未選択から選択する

未選択状態からメニューを開き、複数条件を選択します。選択されると件数バッジが表示されます。

選択済み

選択値がある時は選択済み状態になり、ボタン上に件数バッジを表示します。

カスタムメニュー

内容を差し替えると、色、タグ、容量範囲など、標準リスト以外のフィルター UI を配置できます。

プロパティ

表は横にスクロールできます
プロパティ初期値説明
titlestring"Filter"ボタンに表示するラベルです。
iconReactNode-任意の先頭アイコンです。未指定時はフィルターアイコンを表示します。
optionsFilterOption[]-標準リスト表示に使う選択肢です。
selectedValuesSet<string>-現在選択されている値です。件数バッジと選択済み状態に使われます。
onFilterChange(values: Set<string>) => void-選択値が変わった時に呼ばれます。
clearLabelstring"Clear filters"メニュー内のクリアアクションのラベルです。
selectedLabel(count: number) => string-件数バッジの読み上げ用ラベルを生成します。
contentClassNamestring-開いたメニューに追加するスタイル用クラスです。
contentAlign"start" | "center" | "end""start"ポップオーバーの横位置です。
portalContainerHTMLElement | null-擬似ブラウザや入れ子の表示領域に閉じ込めたい時の表示先です。
childrenReactNode-色、タグ、評価など、標準リスト以外の独自フィルター 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 の記事で解説しています。