Forms
Filter bar
Facet filters together, with active-filter chips, a result count and Clear all.
import { FilterBar, Chip } from '@jsonresume/ui'Source(opens in a new tab)
Examples
97 results
- Remote
Show code
filter-bar/jobs.tsx
'use client';
import { Field, FilterBar, SearchField, Select, Switch } from '@jsonresume/ui';
import { useState } from 'react';
const labels: Record<string, string> = {
fulltime: 'Full-time',
contract: 'Contract',
senior: 'Senior',
lead: 'Lead',
};
export default function FilterBarJobs() {
const [type, setType] = useState('');
const [level, setLevel] = useState('');
const [remote, setRemote] = useState(true);
const active = [
type && {
key: 'type',
label: labels[type] ?? type,
onRemove: () => setType(''),
},
level && {
key: 'level',
label: labels[level] ?? level,
onRemove: () => setLevel(''),
},
remote && {
key: 'remote',
label: 'Remote',
onRemove: () => setRemote(false),
},
].filter((f): f is { key: string; label: string; onRemove: () => void } =>
Boolean(f)
);
return (
<FilterBar
active={active}
resultCount={128 - active.length * 31}
onClearAll={() => {
setType('');
setLevel('');
setRemote(false);
}}
>
<Field label="Search">
<SearchField placeholder="Title or company" />
</Field>
<Field label="Type">
<Select value={type} onChange={(e) => setType(e.target.value)}>
<option value="">Any</option>
<option value="fulltime">Full-time</option>
<option value="contract">Contract</option>
</Select>
</Field>
<Field label="Level">
<Select value={level} onChange={(e) => setLevel(e.target.value)}>
<option value="">Any</option>
<option value="senior">Senior</option>
<option value="lead">Lead</option>
</Select>
</Field>
<Switch
label="Remote only"
checked={remote}
onCheckedChange={setRemote}
/>
</FilterBar>
);
}Usage
Do
- Apply filters as they change; show the result count.
- Name chips with the value, not the field ("Remote").
Don’t
- Add an Apply button for instant filters.
Accessibility
- A named region; the result count is announced politely.
- Each chip has a "Remove <filter>" button.
Props
<FilterBar>
| Prop | Type | Default | Description |
|---|---|---|---|
| children required | ReactNode | – | The filter controls: Selects, SearchField, Switches. |
| active | ActiveFilter[] | [] | |
| label | string | Filters | |
| onClearAll | (() => void) | – | |
| resultCount | number | – | Result count, announced politely when it changes. |
| resultLabel | ((count: number) => string) | (n) => `${n} ${n === 1 ? 'result' : 'results'}` |
<Chip>
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | – | Plain-text name used in the remove button's label. |
| onRemove | (() => void) | – | Shows a remove button labelled "Remove <label>". |