Design System

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