react-filters-header
v1.0.2
Published
A set of URL-param-driven filter components for React apps — text input, select, multi-select, boolean toggle, search-select, and date input. Zero UI-framework dependencies.
Maintainers
Readme
react-filters-header
react-filters-header is a lightweight React filter bar that keeps filter values in URL query params.
Official Links
- npm: https://www.npmjs.com/package/react-filters-header
- Live guide: https://react-filters-header-demo.vercel.app/
- GitHub: https://github.com/alitkturners/react-filters-header
- Issues: https://github.com/alitkturners/react-filters-header/issues
Live Guide Website
For a full visual user guide with live examples, styling ideas, and implementation patterns, visit:
If you get stuck, start from this guide first and compare your implementation with the live examples.
Use one component (FiltersHeader) and pass a filters array.
It supports:
- text input (
text_input) - single select (
select_input) - multi select (
multiselector) - boolean toggle (
boolean) - searchable select (
search_select) - date picker (
date_input)
Installation
npm install react-filters-headerAlso import styles once:
import 'react-filters-header/dist/index.css';Peer dependency:
react >= 17
Next.js Support
Yes, it works with Next.js.
- Use
FiltersHeaderinside a Client Component ('use client'). - Import CSS once globally (
app/layout.tsxorpages/_app.tsx):import 'react-filters-header/dist/index.css';
Quick Start
import { useState } from 'react';
import { FiltersHeader, type FilterConfig } from 'react-filters-header';
import 'react-filters-header/dist/index.css';
export default function Example() {
const [assigneeSearch, setAssigneeSearch] = useState('');
const filters: FilterConfig[] = [
{
name: 'q',
label: 'Search',
type: 'text_input',
placeholder: 'Search tickets',
},
{
name: 'status',
label: 'Status',
type: 'select_input',
options: [
{ label: 'Open', name: 'open' },
{ label: 'Closed', name: 'closed' },
],
},
{
name: 'tags',
label: 'Tags',
type: 'multiselector',
options: [
{ label: 'Bug', name: 'bug' },
{ label: 'Feature', name: 'feature' },
],
},
{
name: 'archived',
label: 'Archived',
type: 'boolean',
},
{
name: 'assignee',
label: 'Assignee',
type: 'search_select',
searchOptions: [
{ label: 'Alice', value: '1' },
{ label: 'Bob', value: '2' },
],
search: assigneeSearch,
setSearch: setAssigneeSearch,
},
{
name: 'created_at',
label: 'Created Date',
type: 'date_input',
},
];
return (
<FiltersHeader
filters={filters}
debounceMs={400}
pagination={{ page: 0, pageSize: 20 }}
/>
);
}How URL Sync Works
- Changing a filter updates the URL query string.
- Empty values are removed from URL params.
- If
paginationis passed, filter changes reset:page=0pageSize=<your pageSize>
Example URL:
?q=server&status=open&tags=bug,feature&archived=true&created_at=2026-03-07Read params in your page:
const params = new URLSearchParams(window.location.search);
const q = params.get('q');
const createdAt = params.get('created_at');FiltersHeader Props
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| filters | FilterConfig[] | required | Filter definitions |
| pagination | { page: number; pageSize: number } | undefined | Resets page on filter change |
| debounceMs | number | 500 | Debounce for text_input |
| cssProperties | React.CSSProperties | undefined | Container inline styles |
| containerClassName | string | undefined | Extra class for container |
FilterConfig Shape
type FilterType =
| 'text_input'
| 'select_input'
| 'multiselector'
| 'boolean'
| 'search_select'
| 'date_input';
interface FilterConfig {
name: string; // query param name
label: string;
type: FilterType;
placeholder?: string;
cssProperties?: React.CSSProperties;
// select_input / multiselector
options?: { label: string; name: string }[];
allLabel?: string;
// search_select
searchOptions?: { label: string; value: string | number }[];
search?: string;
setSearch?: (value: string) => void;
}Troubleshooting
- Styles not showing:
- Ensure this import exists once in your app:
import 'react-filters-header/dist/index.css';
- Ensure this import exists once in your app:
- URL params not updating:
- Ensure each filter has a unique
name. - Ensure the component renders in browser context (not server-only).
- Ensure each filter has a unique
search_selectnot filtering:- Pass
searchandsetSearchand updatesearchOptionsbased on the currentsearchvalue.
- Pass
For complete troubleshooting flows and side-by-side examples, use the live guide:
