Search By Chips Block
The SearchByChip Component is a fully customizable and accessible search by chips interface built with React and TypeScript. It provides a complete chip-based search experience with modern design patterns, clickable chip sections, and flexible customization options for filtering and searching functionality.
π Installationβ
npm install @nodeblocks/frontend-search-by-chip-block@0.1.3
π Usageβ
import {SearchByChip} from '@nodeblocks/frontend-search-by-chip-block';
- Basic Usage
- Advanced Usage
function BasicSearchByChips() {
const handleChipClick = (value: string) => {
console.log('Chip clicked:', value);
// Handle search logic here
};
const searchChips = [
{ value: 'electronics', label: 'Electronics' },
{ value: 'clothing', label: 'Clothing' },
{ value: 'books', label: 'Books' },
{ value: 'home-garden', label: 'Home & Garden' },
{ value: 'sports', label: 'Sports' }
];
return (
<SearchByChip
searchByChipTitle="Quick Search"
subtitle="Find what you're looking for"
sectionTitle="Categories"
onClickChip={handleChipClick}
chips={searchChips}>
<SearchByChip.Title />
<SearchByChip.Subtitle />
<SearchByChip.ChipSection />
</SearchByChip>
);
}
function AdvancedSearchByChips() {
const handleChipClick = (value: string) => {
console.log('Chip clicked:', value);
// Handle search logic here
};
const searchChips = [
{ value: 'electronics', label: 'Electronics' },
{ value: 'clothing', label: 'Clothing' },
{ value: 'books', label: 'Books' },
{ value: 'home-garden', label: 'Home & Garden' },
{ value: 'sports', label: 'Sports' }
];
return (
<SearchByChip
searchByChipTitle="Quick Search"
subtitle="Find what you're looking for"
sectionTitle="Categories"
onClickChip={handleChipClick}
chips={searchChips}>
{({ defaultBlocks, defaultBlockOrder }) => ({
blocks: {
...defaultBlocks,
// π Custom Title with props override
title: {
...defaultBlocks.title,
props: {
...defaultBlocks.title.props,
className: "custom-search-title",
style: {
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
fontSize: '2.5rem',
fontWeight: 'bold',
textAlign: 'center',
marginBottom: '10px'
},
children: "π Smart Search Experience"
},
},
// π Custom Subtitle with props override
subtitle: {
...defaultBlocks.subtitle,
props: {
...defaultBlocks.subtitle.props,
className: "custom-search-subtitle",
style: {
color: '#6c757d',
fontSize: '1.1rem',
textAlign: 'center',
marginBottom: '40px',
fontWeight: '400'
},
children: "Discover exactly what you need with our intelligent category filters"
},
},
// π·οΈ Rich Chip Section with full component override
chipSection: (
<div style={{
padding: '30px',
backgroundColor: '#f8f9fa',
borderRadius: '16px',
border: '1px solid #e9ecef'
}}>
<h3 style={{
color: '#495057',
fontSize: '1.3rem',
fontWeight: '600',
marginBottom: '20px',
textAlign: 'center'
}}>
β¨ Popular Categories
</h3>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
gap: '15px',
marginBottom: '25px'
}}>
{[
{ value: 'tech', label: 'π» Technology', color: '#007bff', bgColor: '#e3f2fd' },
{ value: 'fashion', label: 'π Fashion', color: '#e91e63', bgColor: '#fce4ec' },
{ value: 'books', label: 'π Books', color: '#ff9800', bgColor: '#fff3e0' },
{ value: 'home', label: 'π Home & Garden', color: '#4caf50', bgColor: '#e8f5e8' },
{ value: 'sports', label: 'β½ Sports', color: '#9c27b0', bgColor: '#f3e5f5' },
{ value: 'health', label: 'π Health', color: '#00bcd4', bgColor: '#e0f2f1' }
].map((chip, index) => (
<button
key={index}
onClick={() => handleChipClick(chip.value)}
style={{
backgroundColor: chip.bgColor,
border: `2px solid ${chip.color}`,
borderRadius: '12px',
padding: '15px 20px',
fontSize: '0.95rem',
fontWeight: '500',
cursor: 'pointer',
transition: 'all 0.3s ease',
textAlign: 'center',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
color: chip.color
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = chip.color;
e.currentTarget.style.color = 'white';
e.currentTarget.style.transform = 'translateY(-3px)';
e.currentTarget.style.boxShadow = `0 8px 25px ${chip.color}30`;
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = chip.bgColor;
e.currentTarget.style.color = chip.color;
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = 'none';
}}
>
{chip.label}
</button>
))}
</div>
{/* Trending Tags */}
<div style={{ marginTop: '30px' }}>
<h4 style={{
color: '#6c757d',
fontSize: '1rem',
fontWeight: '600',
marginBottom: '15px',
textAlign: 'center'
}}>
π₯ Trending Now
</h4>
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '10px',
justifyContent: 'center'
}}>
{['AI Tools', 'Sustainable Living', 'Work From Home', 'Fitness', 'Cooking'].map((tag, index) => (
<span
key={index}
style={{
backgroundColor: '#fff',
border: '1px solid #dee2e6',
borderRadius: '20px',
padding: '6px 14px',
fontSize: '0.85rem',
color: '#6c757d',
cursor: 'pointer',
transition: 'all 0.2s ease'
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor = '#007bff';
e.currentTarget.style.color = 'white';
e.currentTarget.style.borderColor = '#007bff';
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = '#fff';
e.currentTarget.style.color = '#6c757d';
e.currentTarget.style.borderColor = '#dee2e6';
}}
>
{tag}
</span>
))}
</div>
</div>
</div>
),
},
blockOrder: defaultBlockOrder,
})}
</SearchByChip>
);
}
π§ Props Referenceβ
Main Component Propsβ
| Prop | Type | Default | Description |
|---|---|---|---|
searchByChipTitle | ReactNode | Required | Main title for the search by chip section |
sectionTitle | ReactNode | Required | Title for the chip section |
subtitle | ReactNode | Required | Subtitle text displayed below the main title |
onClickChip | (value: string) => void | Required | Callback function triggered when a chip is clicked |
chips | { value: string; label: string }[] | Required | Array of chip objects to display |
className | string | undefined | Additional CSS class name for styling the container |
children | BlocksOverride | undefined | Function to override default blocks or add custom chip components |
Note: The main component inherits all HTML div element props.
Sub-Componentsβ
The SearchByChip component provides several sub-components. All sub-components receive their default values from the main component's context and can override these values through props.
SearchByChip.Titleβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | searchByChipTitle from context | Custom content to override default title rendering |
Note: This component inherits all HTML h4 element props.
SearchByChip.Subtitleβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | subtitle from context | Custom content to override default subtitle rendering |
Note: This component inherits all HTML h6 element props.
SearchByChip.SectionTitleβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | sectionTitle from context | Custom content to override default section title rendering |
Note: This component inherits all HTML h6 element props.
SearchByChip.ChipItemβ
| Prop | Type | Default | Description |
|---|---|---|---|
onClickChip | (value: string) => void | Required | Callback function for chip click events |
value | string | Required | Unique value identifier for the chip |
label | ReactNode | Required | Display text for the chip |
Note: This component inherits all HTML button element props.
SearchByChip.ChipIconβ
This component accepts no props and renders a checkmark SVG icon.
SearchByChip.ChipSectionβ
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Default chip rendering | Custom content to override default chip section rendering |
chips | { value: string; label: string }[] | From context | Array of chip objects to display |
sectionTitle | ReactNode | From context | Title for the chip section |
Note: This component inherits all HTML div element props.
π§ TypeScript Supportβ
Full TypeScript support with comprehensive type definitions:
import {SearchByChip} from '@nodeblocks/frontend-search-by-chip-block';
import {ComponentProps, ReactNode} from 'react';
interface Chip {
value: string;
label: string;
}
// Main component interface
interface SearchByChipProps extends Omit<ComponentProps<'div'>, 'children'> {
searchByChipTitle: ReactNode;
sectionTitle: ReactNode;
subtitle: ReactNode;
onClickChip: (value: string) => void;
chips: Chip[];
className?: string;
}
// Sub-component interfaces
interface ChipItemProps extends ComponentProps<'button'> {
onClickChip: (value: string) => void;
value: string;
label: ReactNode;
}
interface ChipSectionProps
extends Partial<
ComponentProps<'div'> & {
chips: Chip[];
sectionTitle: ReactNode;
}
> {
children?: ReactNode;
}
// Usage example with comprehensive typing
interface CustomSearchData {
categories: Chip[];
onSearch: (searchValue: string) => void;
title: string;
description: string;
}
const SearchComponent = ({categories, onSearch, title, description}: CustomSearchData) => {
const handleChipSelection = (value: string) => {
onSearch(value);
// Additional search logic
};
return (
<SearchByChip
searchByChipTitle={title}
sectionTitle="Categories"
subtitle={description}
onClickChip={handleChipSelection}
chips={categories}
onClick={e => console.log('Container clicked')}>
<SearchByChip.Title />
<SearchByChip.Subtitle />
<SearchByChip.ChipSection />
</SearchByChip>
);
};
Built with β€οΈ using React, TypeScript, and modern web standards.