メインコンテンツまでスキップ

Filter Search Panelブロック

FilterSearchPanel は、送信型検索フィールド、フィルター設定ボタン、削除可能なフィルターチップを備えた、MUI 上に構築された検索・フィルターツールバーです。

インストール

npm install @nodeblocks/frontend-filter-search-panel-block

必要なもの

項目用途
filtersパネルに表示するアクティブなフィルターチップ({ label, key, groupName? }
defaultSearchValue検索フィールドの初期値
onSearchフォーム送信時にパース済みフォームデータで呼び出される(デフォルトフィールド: search
onSearchChange制御型検索が必要なときに検索入力の変更イベントを受け取る
onClickRemoveFilterユーザーがチップを削除したときにチップを除去する
onClickFilterButtonフィルター UI(モーダル、ドロワー、ルートなど)を開く
searchPlaceholderSearchInput で使用するプレースホルダーテキスト
noFilterTextフィルターが選択されていないときに表示するテキスト
filterLabelフィルター設定ボタンに表示するラベル
親が所有するフィルター状態

FilterSearchPanelfilters 配列を保持しません。チップはアプリの状態で管理し、onClickRemoveFilter(および他の場所でフィルターを適用するとき)で更新してください。

コード例

ライブエディター
function Example() {
  const defaultFilters = [
    {label: 'Active', key: 'status-active'},
    {label: 'Inactive', key: 'status-inactive'},
  ];

  const filterCatalog = [
    {label: 'Active', key: 'status-active'},
    {label: 'Inactive', key: 'status-inactive'},
    {label: 'Remote', key: 'work-remote', groupName: 'Work type'},
    {label: 'Full-time', key: 'employment-full-time', groupName: 'Employment'},
    {label: 'Contract', key: 'employment-contract', groupName: 'Employment'},
  ];

  const [filters, setFilters] = React.useState(defaultFilters);
  const handleRemoveFilter = filter => {
    setFilters(current => current.filter(f => f.key !== filter.key));
  };

  const handleFilterButton = () => {
    const nextFilter = filterCatalog.find(option => !filters.some(f => f.key === option.key));

    if (nextFilter) {
      setFilters(current => [...current, nextFilter]);
    }
  };

  const handleSearch = ({search}) => {
    if (!search?.trim()) {
      return;
    }

    setFilters(current => [...current, {label: search, key: `search-${Date.now()}`, groupName: 'Search'}]);
  };

  return (
    <FilterSearchPanel
      filters={filters}
      searchPlaceholder="サービスを検索..."
      noFilterText="フィルターが適用されていません"
      filterLabel="フィルター設定"
      onClickFilterButton={handleFilterButton}
      onClickRemoveFilter={handleRemoveFilter}
      onSearch={handleSearch}
    />
  );
}
結果
Loading...

主要プロパティ

コアプロパティ

プロパティ必須デフォルト説明
filtersFilterChip[]いいえ[]パネルに表示する選択済みフィルターチップ
defaultSearchValuestringいいえundefinedSearchInput で使用する初期値
onSearch(data: T) => voidいいえundefinedフォーム送信時に呼び出される。T のデフォルトは { search: string }
onSearchChange(event: React.ChangeEvent<HTMLInputElement>) => voidいいえundefined検索フィールドの変更ハンドラー。制御型検索入力で一般的に使用
onClickRemoveFilter(filter: FilterChip) => voidいいえundefinedチップの削除アイコンがクリックされたときに呼び出される
onClickFilterButton() => voidいいえundefinedフィルター設定ボタンがクリックされたときに呼び出される

コンテンツプロパティ

プロパティ必須デフォルト説明
searchPlaceholderstringいいえフリーワードで検索検索入力に表示するプレースホルダー
noFilterTextstringいいえ条件未設定フィルターが選択されていないときに表示するテキスト
filterLabelstringいいえ絞込み設定フィルター設定ボタンに表示するラベル

レイアウトと構成プロパティ

プロパティ必須デフォルト説明
childrenBlocksOverride | ReactNodeいいえundefinedデフォルトブロックをオーバーライドする、または複合コンポーネントの子をレンダリングする
classNamestringいいえundefinedルートフォームのクラス名
sxSxPropsいいえundefinedルートフォーム用の MUI システムスタイル
spacingStackProps['spacing']いいえ{ xs: 1.5, sm: 2.5 }ルートブロック間のスペース
directionStackProps['direction']いいえ'column'ルートスタックの flex 方向

FilterSearchPanelStackPropschildrencomponentonSubmit を除く)を継承し、form としてレンダリングされます。送信は内部で処理され、指定時は onSearch が呼び出されます。

サブコンポーネントのプロパティ

サブコンポーネントはルートとコンテキストを共有するため、デフォルトではコンテキストのプロパティ値を使用しますが、ローカルでオーバーライドできます。

サブコンポーネント主要プロパティ継承元
FilterSearchPanel.SearchInputsearchPlaceholder, defaultSearchValue, onSearchChange, name, typeTextField
FilterSearchPanel.FilterButtonfilterLabel, onClickFilterButton, childrenButton
FilterSearchPanel.SelectedFilterListfilters, noFilterText, onClickRemoveFilter, childrenBox
FilterSearchPanel.FilterBadgefilter (必須), onClickRemoveFilter, childrenChip
FilterSearchPanel.ActionGroupchildren (デフォルト: フィルターボタン + チップリスト)Stack

デフォルト UI ブロック

ブロックベース備考
FilterSearchPanel (ルート)Stackform としてレンダリング送信を内部で処理し、子ブロックに検索/フィルターコンテキストを提供する
FilterSearchPanel.SearchInputTextField + 送信 IconButtonname="search", size="small"。検索アイコンでフォームを送信する
FilterSearchPanel.ActionGroupStack横並び: フィルターボタン + 選択済みチップ(スクロール可能)

デフォルトのレンダリング順: searchInputactionGroup

追加フィールドプリミティブ

プリミティブベース備考
FilterSearchPanel.FilterButtonButton + Tune icononClickFilterButton 経由でフィルター UI を開く。デフォルトラベルは 絞込み設定
FilterSearchPanel.SelectedFilterListBox + Typography空のときは noFilterText条件未設定)を表示し、それ以外は groupName でチップをグループ化する
FilterSearchPanel.FilterBadgeChip削除可能なチップ。削除時に onClickRemoveFilter(filter) を呼び出す

TypeScript

import * as React from 'react';
import {FilterSearchPanel} from '@nodeblocks/frontend-filter-search-panel-block';

type FilterChip = {
label: string;
key: string;
groupName?: string;
};

type SearchFormData = {
search: string;
};

const filterCatalog: FilterChip[] = [
{label: 'Remote', key: 'work-remote', groupName: 'Work type'},
{label: 'Full-time', key: 'employment-full-time', groupName: 'Employment'},
];

export function ServiceSearchToolbar() {
const [filters, setFilters] = React.useState<FilterChip[]>([
{label: 'Active', key: 'status-active', groupName: 'Status'},
]);

const handleRemoveFilter = (filter: FilterChip) => {
setFilters(current => current.filter(f => f.key !== filter.key));
};

const handleFilterButton = () => {
const nextFilter = filterCatalog.find(option => !filters.some(f => f.key === option.key));

if (nextFilter) {
setFilters(current => [...current, nextFilter]);
}
};

const handleSearch = (data: SearchFormData) => {
const search = data.search.trim();
if (!search) {
return;
}

setFilters(current => [...current, {label: search, key: `search-${Date.now()}`, groupName: 'Search'}]);
};

return (
<FilterSearchPanel<SearchFormData>
filters={filters}
searchPlaceholder="サービスを検索..."
noFilterText="フィルターが適用されていません"
filterLabel="フィルター設定"
onClickFilterButton={handleFilterButton}
onClickRemoveFilter={handleRemoveFilter}
onSearch={handleSearch}
/>
);
}