Skip to main content
Version: 1.0.3

Advanced Search Form

A comprehensive search interface that combines powerful filtering, saved searches, faceted navigation, and export capabilities. Perfect for admin dashboards, user management systems, and data exploration tools. Features include real-time filtering, saved search management, multiple export formats, theme customization, and comprehensive debugging tools.

Installation

ignix add component advanced-search-form

Basic Usage

import { useState, useCallback } from 'react';
import {
AdvancedSearchForm,
SearchFilters,
SearchActions,
SearchSavedSearches,
SearchFacetedHints,
SearchResultsCount,
SearchTextFilter,
SearchSelectFilter,
SearchMultiSelectFilter,
SearchDateRangeFilter,
SearchNumericRangeFilter,
} from '@ignix-ui/advanced-search-form';

const roleOptions = [
{ value: "admin", label: "Admin", count: 5 },
{ value: "manager", label: "Manager", count: 4 },
{ value: "user", label: "User", count: 5 },
{ value: "developer", label: "Developer", count: 4 },
{ value: "designer", label: "Designer", count: 2 },
];

const statusOptions = [
{ value: "active", label: "Active", count: 12 },
{ value: "inactive", label: "Inactive", count: 4 },
{ value: "pending", label: "Pending", count: 3 },
{ value: "suspended", label: "Suspended", count: 1 },
];

const departmentOptions = [
{ value: "engineering", label: "Engineering", count: 7 },
{ value: "sales", label: "Sales", count: 5 },
{ value: "marketing", label: "Marketing", count: 4 },
{ value: "hr", label: "Human Resources", count: 3 },
{ value: "finance", label: "Finance", count: 4 },
];

const locationOptions = [
{ value: "new york", label: "New York", count: 6 },
{ value: "los angeles", label: "Los Angeles", count: 3 },
{ value: "chicago", label: "Chicago", count: 4 },
{ value: "san francisco", label: "San Francisco", count: 4 },
{ value: "seattle", label: "Seattle", count: 3 },
];

const facetedCategories = [
{ id: "role", label: "Role", options: roleOptions },
{ id: "status", label: "Status", options: statusOptions },
{ id: "department", label: "Department", options: departmentOptions },
];

const savedSearches = [
{ id: "1", name: "Active Admins", filters: { role: "admin", status: ["active"] } },
{ id: "2", name: "Sales Team", filters: { department: "sales", status: ["active"] } },
{ id: "3", name: "High Performers", filters: { scoreRange: { min: 85 } } },
{ id: "4", name: "Engineering Team", filters: { department: "engineering", status: ["active"] } },
];

// Mock user data
const mockUsers = [
{ id: 1, name: "John Doe", role: "admin", status: "active", department: "engineering", location: "New York", age: 32, score: 95, salary: 95000, created: "2024-01-15" },
{ id: 2, name: "Jane Smith", role: "user", status: "active", department: "sales", location: "Los Angeles", age: 28, score: 88, salary: 75000, created: "2024-02-20" },
{ id: 3, name: "Bob Johnson", role: "manager", status: "inactive", department: "marketing", location: "Chicago", age: 45, score: 76, salary: 85000, created: "2023-12-10" },
{ id: 4, name: "Alice Brown", role: "admin", status: "active", department: "finance", location: "Boston", age: 35, score: 92, salary: 82000, created: "2024-01-05" },
{ id: 5, name: "Charlie Wilson", role: "developer", status: "pending", department: "engineering", location: "San Francisco", age: 24, score: 67, salary: 70000, created: "2024-02-28" },
{ id: 6, name: "Diana Prince", role: "manager", status: "active", department: "engineering", location: "New York", age: 38, score: 94, salary: 105000, created: "2023-11-20" },
{ id: 7, name: "Eve Adams", role: "developer", status: "active", department: "engineering", location: "Seattle", age: 26, score: 89, salary: 90000, created: "2024-03-01" },
{ id: 8, name: "Frank Castle", role: "designer", status: "active", department: "marketing", location: "Austin", age: 42, score: 71, salary: 72000, created: "2023-10-15" },
];

function App() {
const [activeFilters, setActiveFilters] = useState({});
const [filteredResults, setFilteredResults] = useState(mockUsers);

const handleSearch = () => {
let results = [...mockUsers];

if (activeFilters.name) {
results = results.filter(u =>
u.name.toLowerCase().includes(activeFilters.name.toLowerCase())
);
}
if (activeFilters.role) {
results = results.filter(u =>
u.role.toLowerCase() === activeFilters.role.toLowerCase()
);
}
if (activeFilters.department) {
results = results.filter(u =>
u.department.toLowerCase() === activeFilters.department.toLowerCase()
);
}
if (activeFilters.status && Array.isArray(activeFilters.status)) {
results = results.filter(u =>
activeFilters.status.includes(u.status.toLowerCase())
);
}

setFilteredResults(results);
};

return (
<AdvancedSearchForm variant="dark" layout="stacked">
<div className="space-y-6">
<SearchFilters>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<SearchSelectFilter
filter={{ id: "role", label: "Role", type: "select", options: roleOptions }}
value={activeFilters.role || ""}
onChange={(val) => setActiveFilters({ ...activeFilters, role: val })}
/>
<SearchSelectFilter
filter={{ id: "department", label: "Department", type: "select", options: departmentOptions }}
value={activeFilters.department || ""}
onChange={(val) => setActiveFilters({ ...activeFilters, department: val })}
/>
<SearchMultiSelectFilter
filter={{ id: "status", label: "Status", type: "multi-select", options: statusOptions }}
value={activeFilters.status || []}
onChange={(val) => setActiveFilters({ ...activeFilters, status: val })}
/>
</div>
</SearchFilters>

<SearchActions
onApply={handleSearch}
onReset={() => setActiveFilters({})}
showApply={true}
showReset={true}
/>

<SearchResultsCount count={filteredResults.length} total={mockUsers.length} />

<div className="space-y-2">
{filteredResults.map(user => (
<div key={user.id} className="p-4 border rounded-lg">
<p className="font-semibold">{user.name}</p>
<p className="text-sm text-gray-600">
{user.role}{user.department}{user.status}
</p>
</div>
))}
</div>
</div>
</AdvancedSearchForm>
);
}

Features

  • Multiple filter types (text, select, multi-select, date range, checkbox, numeric range)
  • Responsive (mobile, tablet, desktop)
  • Auto-apply with debounce
  • Saved searches
  • Faceted filtering (quick refine)
  • Export support (CSV, Excel, JSON)
  • Collapsible filters (mobile optimized)
  • Theming (light/dark)
  • Fully composable architecture

Props

AdvancedSearchForm Props

PropTypeDefaultDescription
variant'default' | 'dark' | 'light''default'Visual theme variant
layout'inline' | 'stacked' | 'collapsible''stacked'Layout style for filters
filtersFilterConfig[][]Array of filter configurations
facetedCategoriesFacetedCategory[]Categories for faceted search hints
onSearch(filters: Record<string, FilterValue>) => voidCalled when search is triggered
onExport(filters: Record<string, FilterValue>, format: ExportFormat) => voidCalled when export is triggered
onSaveSearch(search: SavedSearch) => voidCalled when saving a search
onDeleteSearch(searchId: string) => voidCalled when deleting a saved search
initialFiltersRecord<string, FilterValue>{}Initial filter values
savedSearchesSavedSearch[][]Predefined saved searches
resultsCountnumberCurrent number of results
totalResultsnumberTotal number of results
autoApplybooleanfalseApply filters automatically as they change
debounceMsnumber300Debounce delay for auto-apply in milliseconds
showExportbooleantrueShow export button
showSaveSearchbooleantrueShow save search button
showResetbooleantrueShow reset button
showFacetedbooleantrueShow faceted search hints
showResultsCountbooleantrueShow results count
classNamestringAdditional CSS classes
childrenReact.ReactNodeCustom child components
ariaLabelstring'Advanced search form'ARIA label for accessibility
mobileBreakpointnumber768Breakpoint for mobile layout in pixels
tabletBreakpointnumber1024Breakpoint for tablet layout in pixels
defaultCollapsedOnMobilebooleantrueCollapse filters panel on mobile by default

SearchFilters Props

PropTypeDefaultDescription
childrenReact.ReactNodeCustom filter components
classNamestringAdditional CSS classes

SearchActions Props

PropTypeDefaultDescription
onApply() => voidCalled when apply button is clicked
onReset() => voidCalled when reset button is clicked
onSave() => voidCalled when save button is clicked
onExport() => voidCalled when export button is clicked
showApplybooleantrueShow apply button (hidden when autoApply is true)
showResetbooleantrueShow reset button
showSavebooleantrueShow save button
showExportbooleantrueShow export button
classNamestringAdditional CSS classes

SearchSavedSearches Props

PropTypeDefaultDescription
searchesSavedSearch[]Saved searches to display
onApply(search: SavedSearch) => voidCalled when a saved search is applied
onDelete(searchId: string) => voidCalled when a saved search is deleted
classNamestringAdditional CSS classes

SearchFacetedHints Props

PropTypeDefaultDescription
categoriesFacetedCategory[]Faceted categories to display
onSelect(categoryId: string, value: string) => voidCalled when a facet is selected
classNamestringAdditional CSS classes

SearchResultsCount Props

PropTypeDefaultDescription
countnumberCurrent result count
totalnumberTotal result count
classNamestringAdditional CSS classes

Individual Filter Component Props

ComponentPropsDescription
SearchTextFilterfilter: TextFilterConfig, value: string, onChange: (value: string) => void, className?: stringText input filter
SearchSelectFilterfilter: SelectFilterConfig, value: string, onChange: (value: string) => void, className?: stringSingle-select dropdown filter
SearchMultiSelectFilterfilter: MultiSelectFilterConfig, value: string[], onChange: (value: string[]) => void, className?: stringMulti-select dropdown with checkboxes
SearchDateRangeFilterfilter: DateRangeFilterConfig, value: DateRangeValue, onChange: (value: DateRangeValue) => void, className?: stringDate range picker with presets
SearchCheckboxFilterfilter: CheckboxFilterConfig, value: string[], onChange: (value: string[]) => void, className?: stringCheckbox group filter
SearchNumericRangeFilterfilter: NumericRangeFilterConfig, value: NumericRangeValue, onChange: (value: NumericRangeValue) => void, className?: stringMin/max number inputs
SearchFilterRendererfilter: FilterConfig, value: FilterValue, onChange: (value: FilterValue) => void, className?: stringAutomatic renderer based on filter type