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>) => void—Called when search is triggered
onExport(filters: Record<string, FilterValue>, format: ExportFormat) => void—Called when export is triggered
onSaveSearch(search: SavedSearch) => void—Called when saving a search
onDeleteSearch(searchId: string) => void—Called when deleting a saved search
initialFiltersRecord<string, FilterValue>{}Initial filter values
savedSearchesSavedSearch[][]Predefined saved searches
resultsCountnumber—Current number of results
totalResultsnumber—Total 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
classNamestring—Additional CSS classes
childrenReact.ReactNode—Custom 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.ReactNode—Custom filter components
classNamestring—Additional CSS classes

SearchActions Props​

PropTypeDefaultDescription
onApply() => void—Called when apply button is clicked
onReset() => void—Called when reset button is clicked
onSave() => void—Called when save button is clicked
onExport() => void—Called when export button is clicked
showApplybooleantrueShow apply button (hidden when autoApply is true)
showResetbooleantrueShow reset button
showSavebooleantrueShow save button
showExportbooleantrueShow export button
classNamestring—Additional CSS classes

SearchSavedSearches Props​

PropTypeDefaultDescription
searchesSavedSearch[]—Saved searches to display
onApply(search: SavedSearch) => void—Called when a saved search is applied
onDelete(searchId: string) => void—Called when a saved search is deleted
classNamestring—Additional CSS classes

SearchFacetedHints Props​

PropTypeDefaultDescription
categoriesFacetedCategory[]—Faceted categories to display
onSelect(categoryId: string, value: string) => void—Called when a facet is selected
classNamestring—Additional CSS classes

SearchResultsCount Props​

PropTypeDefaultDescription
countnumber—Current result count
totalnumber—Total result count
classNamestring—Additional 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