Search By Chipsブロック
SearchByChip は、MUI 上に構築されたチップベースのクイック検索ブロックで、タイトル、サブタイトル、1 つ以上のクリック可能なチップセクションを備えています。
インストール
- npm
- yarn
- pnpm
- bun
npm install @nodeblocks/frontend-search-by-chip-block
yarn add @nodeblocks/frontend-search-by-chip-block
pnpm add @nodeblocks/frontend-search-by-chip-block
bun add @nodeblocks/frontend-search-by-chip-block
必要なもの
| 項目 | 用途 |
|---|---|
searchByChipTitle | ブロック上部のメイン見出し |
subtitle | タイトル下の補助テキスト |
chipSections | 各チップグループ、そのラベル、チップ、onClickChip ハンドラーを定義する |
各セクションは独自の onClickChip コールバックを提供します。検索状態の更新、ナビゲーション、API リクエストのトリガーに使用してください。
コード例
- クイックスタート
- 複合コンポーネント
- ブロックのオーバーライド
function Example() { const searchChips = [ {value: 'electronics', label: '電子機器'}, {value: 'clothing', label: '衣類'}, {value: 'books', label: '書籍'}, {value: 'home-garden', label: 'ホーム・ガーデン'}, {value: 'sports', label: 'スポーツ'}, ]; const [selectedValue, setSelectedValue] = React.useState(''); const handleChipClick = value => { setSelectedValue(value); }; const chipSections = [ { sectionTitle: 'カテゴリ', chips: searchChips, onClickChip: handleChipClick, }, ]; return ( <> {selectedValue ? ( <Typography variant="body2" sx={{mb: 2, textAlign: 'center'}}> 選択中: <strong>{selectedValue}</strong> </Typography> ) : null} <SearchByChip searchByChipTitle="クイック検索" subtitle="お探しのものを見つけましょう" chipSections={chipSections} /> </> ); }
レイアウトとスタイルをカスタマイズするために子ブロックを使用します。
function Example() { const searchChips = [ {value: 'electronics', label: '電子機器'}, {value: 'clothing', label: '衣類'}, {value: 'books', label: '書籍'}, ]; const [selectedValue, setSelectedValue] = React.useState(''); const handleChipClick = value => { setSelectedValue(value); }; const chipSections = [ { sectionTitle: 'カテゴリ', chips: searchChips, onClickChip: handleChipClick, }, ]; return ( <> {selectedValue ? ( <Typography variant="body2" sx={{mb: 2, textAlign: 'center'}}> 選択中: <strong>{selectedValue}</strong> </Typography> ) : null} <SearchByChip searchByChipTitle="クイック検索" subtitle="お探しのものを見つけましょう" chipSections={chipSections} > <SearchByChip.Title sx={{color: 'primary.main'}} /> <SearchByChip.Subtitle sx={{mb: 1}} /> <SearchByChip.ChipSections sx={{mt: 3}} /> </SearchByChip> </> ); }
関数の children を使ってデフォルトブロックをオーバーライドし、順序を変更したりカスタムブロックを追加します。
function Example() { const searchChips = [ {value: 'electronics', label: '電子機器'}, {value: 'clothing', label: '衣類'}, {value: 'books', label: '書籍'}, {value: 'home-garden', label: 'ホーム・ガーデン'}, ]; const popularSearchChips = [ {value: 'new-arrivals', label: '新着'}, {value: 'sale', label: 'セール中'}, {value: 'best-sellers', label: 'ベストセラー'}, ]; const [selectedValue, setSelectedValue] = React.useState(''); const handleChipClick = value => { setSelectedValue(value); }; const chipSections = [ { sectionTitle: 'カテゴリ', chips: searchChips, onClickChip: handleChipClick, }, { sectionTitle: '人気の検索', chips: popularSearchChips, onClickChip: handleChipClick, }, ]; return ( <> {selectedValue ? ( <Typography variant="body2" sx={{mb: 2, textAlign: 'center'}}> 選択中: <strong>{selectedValue}</strong> </Typography> ) : null} <SearchByChip searchByChipTitle="クイック検索" subtitle="お探しのものを見つけましょう" chipSections={chipSections} > {({defaultBlocks}) => ({ blocks: { ...defaultBlocks, chipHint: ( <Box sx={{ position: 'relative', alignSelf: 'flex-start', width: 'fit-content', mr: {xs: 2, sm: 4}, mt: 3, px: 1.5, py: 1, bgcolor: 'info.light', borderRadius: 1, fontSize: 'body2.fontSize', color: 'info.dark', textAlign: 'center', whiteSpace: 'nowrap', '&::after': { content: '""', position: 'absolute', top: -10, left: 32, width: 0, height: 0, borderLeft: '10px solid transparent', borderRight: '10px solid transparent', borderBottom: '10px solid', borderBottomColor: 'info.light', }, }} > チップをクリックして結果を絞り込み </Box> ), }, blockOrder: ['subtitle', 'title', 'chipSections', 'chipHint'], })} </SearchByChip> </> ); }
ブロックのオーバーライドを使うタイミング
ブロックの順序変更、デフォルトブロックの差し替え、カスタムブロック(上記の chipHint など)の追加が必要な場合にオーバーライドを使います。チップセクションとクリックハンドラはルートコンポーネントに保持してください。
主要プロパティ
コアプロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
searchByChipTitle | ReactNode | はい | — | SearchByChip.Title でレンダリングされるメインタイトル |
subtitle | ReactNode | はい | — | SearchByChip.Subtitle でレンダリングされるサブタイトル |
chipSections | ChipSection[] | はい | — | チップグループ。各セクションに独自の onClickChip ハンドラがある |
ChipSection の形状:
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
sectionTitle | ReactNode | はい | チップグループの見出し |
chips | ChipOption[] | はい | セクションに表示するチップ |
onClickChip | (value: string) => void | はい | このセクションのチップがクリックされたときに呼び出される |
ChipOption の形状:
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
value | string | はい | onClickChip に渡される識別子 |
label | ReactNode | はい | チップボタンのラベル |
icon | ReactNode | いいえ | チップボタンの任意の startIcon(デフォルトは SearchByChip.ChipIcon) |
レイアウトと構成プロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
children | BlocksOverride | ReactNode | いいえ | undefined | デフォルトブロックをオーバーライドする、または複合子をレンダリングする |
className | string | いいえ | undefined | ルートスタックのクラス名 |
sx | SxProps | いいえ | undefined | ルートスタック用の MUI システムスタイル |
spacing | StackProps['spacing'] | いいえ | { xs: 0.5, sm: 1 } | ルートスタックの垂直方向の間隔 |
SearchByChip は StackProps(children を除く)を継承します。デフォルトの defaultBlockOrder: subtitle、title、sectionTitle、chipIcon、chipItem、chipSection、chipSections(ルートは subtitle、title、chipSections のみをレンダリング)。
サブコンポーネントのプロパティ
サブコンポーネントはルートとコンテキストを共有します。searchByChipTitle、subtitle、chipSections はデフォルトで適用されます。同じキーをサブコンポーネントに渡すとローカルで上書きできます。
| サブコンポーネント | 主要プロパティ | 継承 | ベース |
|---|---|---|---|
SearchByChip.Title | searchByChipTitle、children、variant(h1)、component(h1)、className、sx | TypographyProps | Typography |
SearchByChip.Subtitle | subtitle、children、variant(h6)、component(h6)、className、sx | TypographyProps | Typography |
SearchByChip.ChipSections | chipSections、children、className、sx | StackProps | Stack |
SearchByChip.ChipSection | sectionTitle、chips、onClickChip、children、className | StackProps | Stack + Divider + Box |
SearchByChip.SectionTitle | sectionTitle(必須)、children、variant(h5)、component(h5)、className、sx | TypographyProps | Typography |
SearchByChip.ChipItem | onClickChip(必須)、value(必須)、label(必須)、startIcon(デフォルト ChipIcon)、className、sx | Button props except children | Button(variant="outlined"、size="small") |
SearchByChip.ChipIcon | — | — | Check アイコン |
デフォルト UI ブロック
| ブロック | ベース | 備考 |
|---|---|---|
SearchByChip(ルート) | Stack | タイトル、サブタイトル、チップセクションのコンテキストを提供する中央揃えコンテナ |
SearchByChip.Title | Typography | variant="h1"、レスポンシブなフォントサイズ |
SearchByChip.Subtitle | Typography | プライマリカラー、レスポンシブなタイポグラフィ |
SearchByChip.ChipSections | Stack | chipSections を ChipSection ブロックにマッピングする |
デフォルトのルートレンダリング順序: subtitle → title → chipSections。
chipSection、sectionTitle、chipItem、chipIcon は ChipSections 内で構成され、ルートのブロックレベルではレンダリングされません。
追加フィールドプリミティブ
| プリミティブ | ベース | 備考 |
|---|---|---|
SearchByChip.SectionTitle | Typography | チップセクション見出し 1 件。デフォルト variant="h5"、component="h5" |
SearchByChip.ChipSection | Stack + Divider + Box | 1 つのセクションタイトルとそのチップボタンをレンダリングする |
SearchByChip.ChipItem | Button | アウトラインのチップボタン 1 件。onClickChip(value) を呼び出す |
SearchByChip.ChipIcon | Check アイコン | ChipItem のデフォルト start アイコン |
TypeScript
import * as React from 'react';
import {SearchByChip} from '@nodeblocks/frontend-search-by-chip-block';
import type {ReactNode} from 'react';
type ChipOption = {
value: string;
label: string;
icon?: ReactNode;
};
type ChipSection = {
sectionTitle: ReactNode;
chips: ChipOption[];
onClickChip: (value: string) => void;
};
const categoryChips: ChipOption[] = [
{value: 'electronics', label: '電子機器'},
{value: 'clothing', label: '衣類'},
{value: 'books', label: '書籍'},
];
export function QuickSearchByChips() {
const [query, setQuery] = React.useState('');
const chipSections: ChipSection[] = [
{
sectionTitle: 'カテゴリ',
chips: categoryChips,
onClickChip: value => setQuery(value),
},
];
return (
<SearchByChip
searchByChipTitle="クイック検索"
subtitle={query ? `「${query}」の検索結果を表示中` : 'お探しのものを見つけましょう'}
chipSections={chipSections}
/>
);
}