SearchFilterBar
Generic search and filter toolbar with CRUD action buttons for data tables.
Why This Pattern
Every data table needs search, filters, and action buttons. Without a shared pattern:
- Each domain implements its own search/filter UI
- Debounce behavior varies (or is missing)
- Filter dropdowns look different across pages
- No consistent placement for CRUD buttons
- Missing dark mode or accessibility in some implementations
Configuration
Interactive Demo
Current Filter State:
{
"query": ""
}Implementation
Basic Usage
import { SearchFilterBar, SearchFilters } from '@stackmates/ui-interactive';
const [filters, setFilters] = useState<SearchFilters>({
query: '',
status: undefined,
priority: undefined,
});
<SearchFilterBar
filters={filters}
onFiltersChange={setFilters}
config={{
statusOptions: [
{ value: 'active', label: 'Active' },
{ value: 'inactive', label: 'Inactive' },
],
searchPlaceholder: 'Search contacts...',
}}
primaryActions={[
{
label: 'Create New',
icon: <PlusIcon />,
onClick: () => setShowCreateModal(true),
},
]}
secondaryActions={[
{ label: 'Export', onClick: handleExport, variant: 'outline' },
{ label: 'Import', onClick: handleImport, variant: 'outline' },
]}
testIdPrefix="contacts"
/>With TypeScript Generics (Domain-Specific Extra Fields)
interface CrmExtraFilters {
industry?: string;
region?: string;
}
const [filters, setFilters] = useState<SearchFilters<CrmExtraFilters>>({
query: '',
extra: { industry: 'tech' },
});
<SearchFilterBar<CrmExtraFilters>
filters={filters}
onFiltersChange={setFilters}
// ...
/>Pattern Checklist
- Debounced search input (configurable delay)
- Status, Priority, Type filter dropdowns
- Single or multi-select filter modes
- Date range filter (optional)
- Primary actions (Create New button) on the right
- Secondary actions (Export, Import) below filters
- Clear all filters button
- Loading spinner during search
- Dark mode support
- Test IDs via testIdPrefix prop