Filters
Provides a filter bar with badges and active tags, allowing users to narrow down search results by multiple criteria simultaneously.
64.9 KB
•Updated on August 21, 2026
Installation
Bash
pnpm dlx shadcn@latest add @spaceui/components-spaceui-filtersUsage
Code
import * as React from 'react'
import { createFilter, Filters, type Filter, type FilterFieldConfig } from '@/components/spaceui/filters'
export default function SpaceUI() {
const [filters, setFilters] = React.useState<Filter[]>([createFilter('priority', 'is_any_of', ['low', 'medium'])])
const fields: FilterFieldConfig[] = [
{
key: 'priority',
label: 'Priority',
type: 'multiselect',
options: [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
],
},
]
return <Filters filters={filters} fields={fields} onChange={setFilters} />
}Examples
Validation
Trigger Button
Small Size
Large Size
Custom Controls
Data Grid
Nuqs
With i18n Support
Virtualized Large Lists
Prefetched Async Options
Async Server-side Search
API Reference
Filters
The main component for displaying and managing a collection of active filters.
| Prop | Type | Default | Description |
|---|---|---|---|
filters | Filter<T>[] | - | Required. The array of active filters. |
fields | FilterFieldsConfig<T> | - | Required. The configuration for available filter fields. |
onChange | (filters: Filter<T>[]) => void | - | Required. Callback fired when filters are added, updated, or removed. |
size | sm|default|lg | default | The size of the filter items and controls. |
trigger | ReactNode | - | Custom element to trigger the "Add Filter" menu. |
showSearchInput | boolean | true | Whether to show the search input in the "Add Filter" menu. |
allowMultiple | boolean | true | Whether to allow multiple filters for the same field. |
enableShortcut | boolean | false | Whether to enable the keyboard shortcut to open the filter menu. |
shortcutKey | string | f | The key used for the shortcut (e.g., "f"). |
shortcutLabel | string | F | The label to display in the shortcut indicator. |
i18n | Partial<FilterI18nConfig> | - | Custom labels and operators for internationalization. |
className | string | - | Additional CSS classes for the container. |
menuPopupClassName | string | - | Additional CSS classes for the filter dropdown menu. |
FilterFieldConfig
Configuration for an individual filterable field.
| Property | Type | Description |
|---|---|---|
key | string | Required. Unique identifier for the field. |
label | string | Required. Human-readable label for the field. |
type | text|select|multiselect|custom|separator | The type of filter input to use. |
icon | ReactNode | Optional icon to display next to the field label. |
options | FilterOption<T>[] | List of options for select and multiselect fields. |
loadOptions | (query: string) => FilterOption<T>[]|Promise<FilterOption<T>[]> | Async options loader for large or remote lists. Called with the current search query - return a prefetched list (ignore the query) or server-side search results. Debounced, with loading/error states and a value-to-label cache. options still seeds the initial view. |
renderOptionList | (props: FilterOptionListRenderProps<T>) => ReactNode | Bring-your-own rendering for the options list, e.g. virtualization with a windowing library of your choice. Receives { options, highlightedIndex, renderOption }; render the scrollable list and call renderOption for each row. Omit for the default plain list. |
operators | FilterOperator[] | Custom operators for this specific field. |
defaultOperator | string | The operator to select by default when adding this field. |
placeholder | string | Placeholder text for text inputs. |
searchable | boolean | Whether the options list should be searchable. |
maxSelections | number | Maximum number of items allowed in multiselect. |
prefix | ReactNode|string | Prefix element for the input field. |
suffix | ReactNode|string | Suffix element for the input field. |
pattern | string | Regex pattern for text input validation. |
validation | (value) => boolean|object | Custom validation function. |
customRenderer | (props) => ReactNode | Custom renderer for the filter value selector. |
customValueRenderer | (values, options) => ReactNode | Custom renderer for the active filter value display. |
fields | FilterFieldConfig<T>[] | Nested fields if this is a group configuration. |
group | string | Group label if this is a group configuration. |
className | string | Additional CSS classes for the field components. |
FilterOption
Structure for options in select and multiselect fields.
| Property | Type | Description |
|---|---|---|
value | T | Required. The internal value of the option. |
label | string | Required. Human-readable label for the option. |
icon | ReactNode | Optional icon to display next to the option. |
className | string | Additional CSS classes for the option item. |
Filter
The structure of an active filter object.
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the filter instance. |
field | string | The key of the associated field configuration. |
operator | string | The selected operator (e.g., "is", "contains"). |
values | T[] | The current value(s) of the filter. |
FilterI18nConfig
Configuration for internationalization and custom labels.
| Property | Type | Description |
|---|---|---|
addFilter | string | Label for the "Add Filter" button. |
searchFields | string | Placeholder for the field search input. |
operators | object | Map of operator keys to localized strings. |
validation | object | Map of validation error messages. |
placeholders | object | Map of dynamic placeholder templates. |
Helpers
| Function | Signature | Description |
|---|---|---|
createFilter | (field, operator?, values?) => Filter | Creates a new filter object with a unique ID. |
createFilterGroup | (id, label, fields, initialFilters?) => FilterGroup | Creates a filter group configuration. |
Keep in mind
- MIT License: Free and open-source for personal and commercial use. Feel free to copy, tweak, and adapt the components to match your exact needs.
- Credits & Inspiration: Some components on this site are inspired by or recreated from great ideas across the web. I'm not here to take credit; just to learn, experiment, and push interface craft further.
- Reach out & Claims: If an attribution was missed, or if you have any inquiry or claim, feel free to reach out directly on X to @adrielzimbril. I'll be glad to update or resolve it right away.
On This Page