チップ検索ブロック
SearchByChipコンポーネントは、ReactとTypeScriptで構築された完全にカスタマイズ可能でアクセシブルなチップ検索インターフェースです。モダンなデザインパターン、クリック可能なチップセクション、フィルタリングと検索機能のための柔軟なカスタマイズオプションを備えた完全なチップベースの検索体験を提供します。
🚀 インストール
npm install @nodeblocks/frontend-search-by-chip-block@0.2.0
📖 使用法
import {SearchByChip} from '@nodeblocks/frontend-search-by-chip-block';
- 基本的な使用法
- 高度な使用法
function SimpleSearchByChip() { const chips = [ {value: 'web', label: 'Web開発'}, {value: 'mobile', label: 'モバイルアプリ'}, {value: 'cloud', label: 'クラウドサービス'}, {value: 'analytics', label: 'データ分析'}, {value: 'ai', label: 'AI & 機械学習'}, ]; const handleChipClick = (value) => { console.log('チップがクリックされました:', value); }; return ( <SearchByChip searchByChipTitle="サービスを検索" sectionTitle="人気のカテゴリ" subtitle="カテゴリで閲覧して必要なものを見つける" onClickChip={handleChipClick} chips={chips} > <SearchByChip.Title /> <SearchByChip.Subtitle /> <SearchByChip.ChipSection /> </SearchByChip> ); }
import {useState} from 'react'; function AdvancedSearchByChip() { const [selectedChip, setSelectedChip] = useState(null); const chips = [ {value: 'trending', label: '🔥 トレンド'}, {value: 'top-rated', label: '⭐ 高評価'}, {value: 'new', label: '🆕 新着'}, {value: 'business', label: '💼 ビジネス'}, {value: 'creative', label: '🎨 クリエイティブ'}, {value: 'analytics', label: '📊 分析'}, {value: 'security', label: '🔒 セキュリティ'}, {value: 'startup', label: '🚀 スタートアップ'}, ]; const handleChipClick = (value) => { setSelectedChip(value); console.log('選択:', value); }; return ( <SearchByChip searchByChipTitle="ソリューションを発見" sectionTitle="カテゴリを閲覧" subtitle="数千の検証済みサービスとツールを検索" onClickChip={handleChipClick} chips={chips} sx={{ background: 'linear-gradient(180deg, #1e1b4b 0%, #312e81 100%)', py: 10, px: 4, minHeight: 400, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', }} > {({defaultBlocks, defaultBlockOrder}) => { const customHeader = ( <div style={{textAlign: 'center', marginBottom: '32px'}}> <div style={{ display: 'inline-flex', alignItems: 'center', gap: '8px', background: 'rgba(255,255,255,0.1)', padding: '8px 16px', borderRadius: '20px', marginBottom: '16px', }} > <div style={{ width: '8px', height: '8px', borderRadius: '50%', background: '#34d399', }} /> <span style={{ color: '#a5b4fc', fontSize: '13px', fontWeight: '500', }} > 10,000以上のソリューションが利用可能 </span> </div> <h1 style={{ color: '#ffffff', fontSize: '48px', fontWeight: '800', margin: '0 0 12px 0', lineHeight: 1.1, }} > 完璧な <br /> <span style={{ background: 'linear-gradient(135deg, #818cf8 0%, #c4b5fd 100%)', backgroundClip: 'text', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', }} > ビジネスソリューションを見つける </span> </h1> <p style={{ color: '#a5b4fc', fontSize: '18px', margin: 0, maxWidth: '500px', }} > 数千の検証済みサービスとツールを検索 </p> </div> ); const customChipSection = ( <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '16px', }} > {selectedChip && ( <div style={{ padding: '8px 16px', background: 'rgba(129,140,248,0.2)', borderRadius: '8px', color: '#c4b5fd', fontSize: '14px', marginBottom: '8px', }} > 選択: {selectedChip} </div> )} <div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px', justifyContent: 'center', maxWidth: '700px', }} > <span style={{ color: '#94a3b8', fontSize: '14px', marginRight: '8px', alignSelf: 'center', }} > 人気: </span> {chips.map((chip, index) => ( <button key={index} onClick={() => handleChipClick(chip.value)} style={{ padding: '10px 18px', borderRadius: '12px', background: selectedChip === chip.value ? 'rgba(129,140,248,0.4)' : 'rgba(255,255,255,0.08)', color: '#e0e7ff', border: '1px solid rgba(255,255,255,0.1)', fontSize: '14px', fontWeight: '500', cursor: 'pointer', transition: 'all 0.2s ease', }} > {chip.label} </button> ))} </div> </div> ); return { blocks: { ...defaultBlocks, title: customHeader, subtitle: <></>, chipSection: customChipSection, }, blockOrder: defaultBlockOrder, }; }} </SearchByChip> ); }
🔧 プロパティリファレンス
メインコンポーネントプロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
searchByChipTitle | ReactNode | 必須 | チップ検索セクションのメインタイトル |
sectionTitle | ReactNode | 必須 | チップセクションのタイトル |
subtitle | ReactNode | 必須 | メインタイトルの下に表示されるサブタイトルテキスト |
onClickChip | (value: string) => void | 必須 | チップがクリックされたときにトリガーされるコールバック関数 |
chips | Chip[] | 必須 | 表示するチップオブジェクトの配列 |
className | string | undefined | コンテナのスタイリング用の追加CSSクラス名 |
sx | SxProps<Theme> | 下記参照 | カスタムスタイリング用のMUIシステムプロパティ |
children | BlocksOverride | undefined | デフォルトブロックをオーバーライドするか、カスタムチップコンポーネントを追加する関数 |
デフォルトsx:
{
p: 2,
gap: 0.5,
bgcolor: 'background.paper',
textAlign: 'center',
containerType: 'inline-size'
}
注意: メインコンポーネントはすべてのMUI Stackプロパティを継承します。
サブコンポーネント
SearchByChipコンポーネントは複数のサブコンポーネントを提供します。すべてのサブコンポーネントは、メインコンポーネントのコンテキストからデフォルト値を受け取り、プロパティを通じてこれらの値をオーバーライドできます。
SearchByChip.Title
検索セクションのメインタイトルをレンダリングします。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | コンテキストのsearchByChipTitle | デフォルトタイトルレンダリングをオーバーライドするカスタムコンテンツ |
searchByChipTitle | ReactNode | コンテキストから | タイトルテキスト(コンテキストをオーバーライド) |
variant | string | 'h4' | Typographyバリアント |
component | ElementType | 'h1' | ルートノードに使用されるコンポーネント |
sx | SxProps<Theme> | undefined | カスタムスタイリング用のMUIシステムプロパティ |
注意: このコンポーネントはすべてのMUI Typographyプロパティを継承します。
SearchByChip.Subtitle
メインタイトルの下にサブタイトルをレンダリングします。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | コンテキストのsubtitle | デフォルトサブタイトルレンダリングをオーバーライドするカスタムコンテンツ |
subtitle | ReactNode | コンテキストから | サブタイトルテキスト(コンテキストをオーバーライド) |
variant | string | 'h6' | Typographyバリアント |
component | ElementType | 'h6' | ルートノードに使用されるコンポーネント |
sx | SxProps<Theme> | { color: 'primary.main' } | カスタムスタイリング用のMUIシステムプロパティ |
注意: このコンポーネントはすべてのMUI Typographyプロパティを継承します。
SearchByChip.SectionTitle
チップセクションのタイトルをレンダリングします。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | コンテキストのsectionTitle | デフォルトセクションタイトルレンダリングをオーバーライドするカスタムコンテンツ |
sectionTitle | ReactNode | コンテキストから | セクションタイトルテキスト(コンテキストをオーバーライド) |
variant | string | 'body1' | Typographyバリアント |
component | ElementType | 'h6' | ルートノードに使用されるコンポーネント |
sx | SxProps<Theme> | 下記参照 | カスタムスタイリング用のMUIシステムプロパティ |
デフォルトsx:
{
px: 2,
py: 1.875,
fontWeight: theme.typography.h6.fontWeight
}
注意: このコンポーネントはすべてのMUI Typographyプロパティを継承します。
SearchByChip.ChipItem
個々のクリック可能なチップボタンをレンダリングします。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
onClickChip | (value: string) => void | 必須 | チップクリックイベントのコールバック関数 |
value | string | 必須 | チップの一意の値識別子 |
label | ReactNode | 必須 | チップの表示テキスト |
startIcon | ReactNode | <SearchByChip.ChipIcon /> | チップの先頭に表示されるアイコン |
variant | 'text' | 'outlined' | 'contained' | 'outlined' | ボタンバリアント |
size | 'small' | 'medium' | 'large' | 'small' | ボタンサイズ |
sx | SxProps<Theme> | 下記参照 | カスタムスタイリング用のMUIシステムプロパティ |
デフォルトsx:
{
'&&': {
fontWeight: theme.typography.fontWeightLight,
py: '7px',
px: 2,
borderColor: 'grey.50',
bgcolor: 'background.paper'
},
'&:hover': {
boxShadow: '0 2px 6px rgba(0, 0, 0, 0.1)'
}
}
注意: このコンポーネントはすべてのMUI Buttonプロパティを継承します(childrenを除く)。
SearchByChip.ChipIcon
チップのデフォルトのチェックマークアイコンをレンダリングします。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
sx | SxProps<Theme> | { width: 16, height: 16, color: 'primary.main' } | カスタムスタイリング用のMUIシステムプロパティ |
注意: このコンポーネントはMUI SvgIconを使用し、チェックマークアイコンをレンダリングします。プロパティは受け取りませんが、デフォルトのスタイリングを使用します。
SearchByChip.ChipSection
セクションタイトルとチップアイテムを含むチップのコンテナをレンダリングします。
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
children | ReactNode | デフォルトチップレンダリング | デフォルトチップセクションレンダリングをオーバーライドするカスタムコンテンツ |
chips | Chip[] | コンテキストから | 表示するチップオブジェクトの配列(コンテキストをオーバーライド) |
sectionTitle | ReactNode | コンテキストから | チップセクションのタイトル(コンテキストをオーバーライド) |
onClickChip | (value: string) => void | コンテキストから | チップクリックのコールバック(コンテキストをオーバーライド) |
sx | SxProps<Theme> | undefined | カスタムスタイリング用のMUIシステムプロパティ |
注意: このコンポーネントはすべてのMUI Stackプロパティを継承します。内部でSearchByChip.SectionTitleとSearchByChip.ChipItem要素を持つflexコンテナをレンダリングします。
🎨 設定例
カスタムタイトルスタイリング
<SearchByChip.Title variant="h3" sx={{color: 'primary.main', fontWeight: 700}} />
カスタムチップアイテムスタイリング
<SearchByChip.ChipItem
value="custom"
label="カスタムチップ"
onClickChip={(value) => console.log(value)}
variant="contained"
sx={{borderRadius: 4, px: 3}}
/>
カスタムチップセクション
<SearchByChip.ChipSection
sx={{
bgcolor: 'grey.50',
borderRadius: 2,
p: 2,
}}
/>
カスタムスタイリング
function CustomStyledSearchByChip() {
const chips = [
{value: 'frontend', label: 'フロントエンド'},
{value: 'backend', label: 'バックエンド'},
{value: 'devops', label: 'DevOps'},
{value: 'design', label: 'デザイン'},
];
return (
<SearchByChip
searchByChipTitle="カテゴリを検索"
sectionTitle="カテゴリを選択"
subtitle="下の人気カテゴリから選択"
onClickChip={value => console.log('クリック:', value)}
chips={chips}
sx={{
bgcolor: 'grey.50',
p: 4,
borderRadius: 3,
}}
>
<SearchByChip.Title
sx={{
color: 'primary.dark',
fontWeight: 700,
fontSize: 28,
}}
/>
<SearchByChip.Subtitle
sx={{
color: 'text.secondary',
mb: 2,
}}
/>
<SearchByChip.ChipSection
sx={{
'& .MuiButton-root': {
bgcolor: 'primary.main',
color: 'white',
borderRadius: 2,
'&:hover': {
bgcolor: 'primary.dark',
},
},
}}
/>
</SearchByChip>
);
}
アイコン付きチップ
function SearchByChipWithIcons() {
const chips = [
{value: 'web', label: 'Web', icon: <span>🌐</span>},
{value: 'mobile', label: 'モバイル', icon: <span>📱</span>},
{value: 'desktop', label: 'デスクトップ', icon: <span>🖥️</span>},
{value: 'cloud', label: 'クラウド', icon: <span>☁️</span>},
];
return (
<SearchByChip
searchByChipTitle="プラットフォーム選択"
sectionTitle="プラットフォームを選択"
subtitle="開発したいプラットフォームを選択"
onClickChip={value => console.log('プラットフォーム:', value)}
chips={chips}
sx={{
p: 4,
bgcolor: '#f8fafc',
borderRadius: 2,
}}
>
<SearchByChip.Title />
<SearchByChip.Subtitle />
<SearchByChip.ChipSection />
</SearchByChip>
);
}
🔧 TypeScriptサポート
包括的な型定義による完全なTypeScriptサポート:
import {SearchByChip} from '@nodeblocks/frontend-search-by-chip-block';
import React from 'react';
interface ChipData {
value: string;
label: string;
icon?: React.ReactNode;
}
function TypedSearchByChip() {
const searchChips: ChipData[] = [
{value: 'react', label: 'React'},
{value: 'typescript', label: 'TypeScript'},
{value: 'nodejs', label: 'Node.js'},
{value: 'graphql', label: 'GraphQL'},
{value: 'aws', label: 'AWS'},
];
const handleChipClick = (value: string): void => {
console.log('選択された技術:', value);
// Navigate or filter logic
};
return (
<SearchByChip
searchByChipTitle="技術を検索"
sectionTitle="人気の技術"
subtitle="チップをクリックして技術でフィルタリング"
onClickChip={handleChipClick}
chips={searchChips}
spacing={3}
sx={{
maxWidth: 800,
mx: 'auto',
p: 4,
}}
>
<SearchByChip.Title />
<SearchByChip.Subtitle />
<SearchByChip.SectionTitle />
<SearchByChip.ChipSection />
</SearchByChip>
);
}
📝 注意事項
- メインコンポーネントはデフォルトでパディング、gap、中央揃えのテキスト配置を持つMUI
Stackを使用します。 - すべてのTypographyコンポーネント(
Title、Subtitle、SectionTitle)はMUITypographyプロパティを継承します。 ChipItemはデフォルトでvariant="outlined"とsize="small"を持つMUIButtonを使用します。- 各チップにはデフォルトの
startIconをオーバーライドするカスタムiconプロパティを設定できます。 - デフォルトの
ChipIconはMUISvgIcon経由でレンダリングされるチェックマークSVGです。 ChipSectionはレスポンシブなチップレイアウトのためにコンテナクエリ(containerType: 'inline-size')を使用します。- コンテキスト値(
searchByChipTitle、subtitle、sectionTitle、chips、onClickChip)はReact Contextを介して共有され、サブコンポーネントレベルでオーバーライドできます。
React、TypeScript、MUIを使用して❤️で構築されました。