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
π 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.