Skip to content
Mendy UI

Filters

Filter API

Props and behavior for the filter components.

On this page

FilterBar and FilterRoot

Start with FilterBar. It renders search, the filter menu, applied chips, suggestions, Clear all, and feedback around a typed controller.

PropDefault / behavior
filtersRequired controller from useFilters, useUrlFilters, or useControlledFilters
searchLabelSearch; accessible label for the search input
searchPlaceholderSearch or filter
searchDebounceMs300; main-search typing pause in milliseconds. 0 uses immediate writes
showCleartrue; show Clear all when a removable filter is active
summary{ mode: "count", limit: 3 }; individual fields can override it
suggestions"always"; also accepts "when-empty" and "never"
closeMenuOnApplyfalse; individual fields can override it
groupsArray of { id, label, fields, separatorBefore?, icon? }
disabledDisable the whole bar
className, classNamesRoot class and named styling overrides

FilterRoot accepts the shared props and children. It supplies the controller to a custom layout; it does not render controls itself. searchLabel, searchPlaceholder, and showClear belong to FilterBar or its composed controls.

ComponentProps / behavior
FilterSearchlabel, placeholder; search with the embedded menu trigger
FilterMenuchildren?, asChild?, anchor?; use anchor for a custom search container
FilterListshowClear = true; chips, suggestions, and trailing Clear all
FilterClearchildren = "Clear all"; clears removable visible fields and search
FilterFeedbackValidation, persistence, and ambiguous recognition feedback
FilterFieldid; render a single chip or suggestion
FilterFieldEditorid, autoFocus = true; put a field editor in your own layout

Search-only bars hide the menu trigger and use the input’s clear control. Menu fields with hidden: true or menu: false do not create a menu trigger. Applied removable chips can still show Clear all.

When placing FilterClear elsewhere, set <FilterList showClear={false} /> to avoid two clear actions.

State hooks

HookUse
useFilters(definitions, options?)Local applied values and search; accepts defaultValues, defaultSearch, and onChange
useUrlFilters(definitions, options)Optional nuqs adapter from @mendylanda/ui/filters/nuqs; requires a persistence scope
useControlledFilters({ definitions, value, onPatch, search? })Bind existing state without changing its shape
useFilterController({ entries, value, search, apply })Lower-level controller when you already have runtime entries
useFilterSearch(value, onChange, delay?, options?)Standalone search draft with immediate clear, flush, optional normalization and context

Controllers expose values, search, entries, active, commit, batch, remove, clear, setSearch, and paste, plus menu/editor state and feedback. batch applies one patch with optional search and source metadata. clear respects hidden, disabled, and non-removable fields. See state and persistence for URL settings and binding existing state for typed mappings.

Definitions

Use defineFilters to preserve inferred types. Factories are select, multiSelect, options, text, tokens, numberRange, dateRange, and custom. The system reference covers field settings, data sources, codecs, recognition, groups, and custom render callbacks.

MendyUIProvider

PropDefault / behavior
menuLayout"anchored"; row-aligned desktop editors. "connected" uses a full-height attached editor
editorAnimationfalse; applies to chip editor popups, independently of chip entrance motion
classNamesNamed classes shared by descendant filter components
componentsTyped replacements for Button, Input, Textarea, Label, and Calendar
portalContainerdocument.body; provide a local theme or dialog element when needed

Nested providers inherit settings; local values override matching keys. Customization describes control contracts and theme tokens.

Standalone primitives

The following components let an application own applied state and editor lifecycle directly. Prefer the typed system above for new filter bars. A standalone chip does not provide query fetching, URL persistence, recognition, or summary resolution by itself.

AppliedFilter

Import from @mendylanda/ui/filters.

PropTypeBehavior
labelstringRequired field name used to build default accessible labels.
childrenReactNodeThe visible summary.
editorReactNodeEnables editing. Omit for a static summary.
onRemove() => voidEnables a separate remove button. Your app clears values or hides the chip.
disabledbooleanDisables edit and remove controls.
openbooleanOptional controlled editor state.
onOpenChange(open: boolean) => voidReports opening and dismissal.
editLabelstringOverrides the default edit accessible label.
removeLabelstringOverrides the default remove accessible label.
contentPropsFilterEditorContentPropsControls alignment, focus callbacks, classes, content label, and opt-in animate.
classNamestringStyles the chip. Other div props are forwarded to it.

Use the low-level composition if you need custom trigger or remove-button markup. Clicks on the convenience component's edit, remove, and editor content are stopped from bubbling into clickable parent containers.

FilterTextEditor

Import from @mendylanda/ui/filters.

PropTypeBehavior
labelstringRequired visible textarea label.
defaultValuestringInitial draft when mounted.
onApply(value: string) => voidReceives the raw draft. Does not close the editor automatically.
validate(value: string) => string | undefinedReturn an error message to prevent submission.
applyLabelstringOptional button text; defaults to Apply.
placeholderstringOptional textarea placeholder.

The default commitMode="enter" saves with Enter and allows new lines with Shift+Enter. Use commitMode="apply" for a custom flow with an explicit button. Close through the parent's onApply callback when desired. Changing defaultValue while the editor is mounted does not overwrite an in-progress draft. Avoid forceMount on content if you want dismissal to discard drafts automatically.

Selection editors

Import FilterSelectEditor and FilterMultiSelectEditor from @mendylanda/ui/filters.

Both accept label, options, searchable, searchPlaceholder, emptyMessage, and autoFocus. Pass autoFocus={false} during a hover preview. An option has a unique string value, a string label, and an optional disabled flag. Search is enabled by default; set searchable={false} to omit it. Search matches label substrings without case sensitivity. Pass your own strings for localization.

FilterSelectEditor takes value and onValueChange. FilterMultiSelectEditor takes values and onValuesChange. Selection changes are immediate and both editors keep the menu open by default. Selecting the current single choice again calls onValueChange with clearValue, an empty string by default. Set removable={false} for a required choice or closeOnSelect to dismiss after selecting. These string-valued standalone callbacks differ from the typed factories, which clear to null by default. Unknown selected values are retained when toggling another option.

Composition components

ComponentUnderlying API
FilterEditorRadix Dropdown Menu root props, with modal={false} by default.
FilterChipDiv props.
FilterEditorTriggershadcn DropdownMenuTrigger props, including asChild.
FilterEditorContentshadcn DropdownMenuContent props; a nonmodal dialog aligned to start by default.
FilterRemoveButton props plus a required aria-label.
FilterMenuItemDropdownMenuSub props plus label, optional icon, and submenu contentProps.
FilterCheckboxItemDropdownMenuCheckboxItem props; prevents dismissal after selection.

Parsing lists

parseFilterValues from @mendylanda/ui/filters splits a string on commas, newlines, and tabs, trims each part, drops empty entries, and removes exact duplicates. It preserves order and case. It is not a CSV parser and does not perform domain-specific validation.

The editor popup uses dialog semantics so it can contain form fields. Built-in selection editors place their choices in a labeled menu inside it. When composing FilterCheckboxItem directly, wrap the options in a labeled role="menu" element. FilterMenuItem accepts contentProps for submenu props. For a submenu containing form fields, pass role="dialog", an aria-label, and aria-orientation={undefined} through contentProps. The trigger then announces that it opens a dialog.

Styling and localization

Components use the consumer's shadcn semantic tokens. Import @mendylanda/ui/styles.css once. Supply classes on composition components or named classNames on the bar. See customization for control replacements and portal containers.

Override editLabel, removeLabel, and contentProps["aria-label"] on AppliedFilter, plus editor labels, placeholders, empty messages, and applyLabel, to translate the interface.