Filter
Shows one filter criterion that opens an editor when pressed. For a list view's whole filter panel, use List view filter panel.
Installation
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- To show one filter criterion, like Account Name contains "Acme", as an item people press to edit it in a popover.
- When the criterion can be new, changed but not saved, invalid or locked, and people need to see which.
- In a filter panel, a report's filters or a builder of conditions, where the page owns the list and the editor's fields.
Don't use it
- For a list view's whole filter panel, with Filter by Owner, filter logic and Save. Use List view filter panel, which is built from these parts.
- For a quick choice that filters as soon as it changes, like a status picker above a table. Use Select or Toggle group.
- To search rows by text. Use an Input or List view header's search.
Usage
Filter
├── FilterMarker
├── FilterItem
│ ├── FilterTrigger
│ │ ├── FilterProperty
│ │ │ └── FilterStatus
│ │ └── FilterPredicate
│ └── FilterRemove
├── FilterError
└── FilterContentimport {
Filter,
FilterContent,
FilterError,
FilterItem,
FilterPredicate,
FilterProperty,
FilterRemove,
FilterStatus,
FilterTrigger,
} from "@/components/wisty/filter"<Filter status="changed" invalid={!!error} open={open} onOpenChange={setOpen}>
<FilterItem>
<FilterTrigger>
<FilterProperty>
Amount
<FilterStatus />
</FilterProperty>
<FilterPredicate>greater than $50,000</FilterPredicate>
</FilterTrigger>
<FilterRemove aria-label="Remove filter: Amount greater than $50,000" />
</FilterItem>
<FilterError>{error}</FilterError>
<FilterContent aria-label="Choose filter criteria">{editor}</FilterContent>
</Filter>FilterContent holds whatever edits the criterion: fields and the buttons that apply or drop them. It adds no buttons of its own. Close it by setting open to false from those buttons. FilterMarker holds a number such as 1. beside the item, for filters that filter logic refers to by position. FilterStatus draws the asterisk after the label of a new or changed criterion. Write it where the asterisk belongs, or leave it out, as Filter by Owner does.
Examples
New, changed and in error
Numbered criteria with FilterMarker: one new, one changed with its FilterStatus asterisk, and one invalid with its FilterError.
Region isn't available to filter by.
Locked with a reason
A locked criterion people can read but not open or remove, with its reason written under it.
This view shows open cases only.
API reference
| Part | Built on | Description |
|---|---|---|
Filter | <div> (opens in a new tab) | One criterion people press to edit: its item, an optional marker, its error and its editor. |
FilterMarker | <span> (opens in a new tab) | |
FilterItem | <div> (opens in a new tab) | |
FilterTrigger | <button> (opens in a new tab) | |
FilterProperty | <span> (opens in a new tab) | |
FilterStatus | <span> (opens in a new tab) | |
FilterPredicate | <span> (opens in a new tab) | |
FilterRemove | Button | |
FilterError | <p> (opens in a new tab) | |
FilterContent | PopoverContent |
Filter
One criterion people press to edit: its item, an optional marker, its error and its editor.
| Prop | Type | Default | Description |
|---|---|---|---|
status | FilterState | "unchanged" | Whether the criterion is saved, new or changed since it was saved. Default "unchanged". |
invalid | boolean | false | The criterion can't be applied; write its reason in FilterError. |
locked | boolean | false | Shown but never edited or removed: the trigger is disabled and the editor never opens. |
open | boolean | Whether the editor is open, controlled. | |
defaultOpen | boolean | Whether the editor is open at first, uncontrolled. | |
onOpenChange | (open: boolean) => void | Called when the editor opens or closes. |
FilterContent
| Prop | Type | Default |
|---|---|---|
align | "center" | "end" | "start" | "end" |
side | "top" | "bottom" | "left" | "right" | "left" |
sideOffset | number | 10 |
FilterStatetype
type FilterState = "unchanged" | "new" | "changed"SLDS mapping
Filter is a criterion's wrapper and FilterItem its slds-filters__item, with slds-is-new for status new or changed, slds-has-error for invalid and slds-is-locked for locked. FilterTrigger is the item's slds-button_reset holding the slds-text-body_small label (FilterProperty) and the value (FilterPredicate). FilterRemove is the small icon button. FilterError is the slds-text-color_error message under the item. FilterContent is slds-popover slds-popover_large opening on the left with slds-nubbin_right-bottom.
Known gaps:
FilterRemoveuses lucide's trash glyph where SLDS drawsutility:delete.- SLDS's grouped filters (
slds-filters__group) and the expression builder's rows aren't parts here.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
status | unchanged (added) | slds-filters__item | |
status | new (added) | slds-filters__item slds-is-new | |
status | changed (added) | slds-filters__item slds-is-new | |
invalid | true (added) | slds-filters__item slds-has-error | |
locked | true (added) | slds-filters__item slds-is-locked |
Accessibility
- The trigger's name is its text, so write the words a screen reader should say first, like an
sr-only"Edit filter 1:", insideFilterTrigger. A new or changed criterion adds "Not saved" or "Changed, not saved" at the end. - Give
FilterRemoveanaria-labelthat names the criterion, andFilterContentanaria-labeloraria-labelledby. invaliddescribes the trigger withFilterError's text, so write the error wheneverinvalidis true.- A locked trigger is disabled, so write the reason as visible text beside it.
Rules
- Pass
status,invalidandlockedfrom the data the page holds. The filter never works out whether a criterion changed or can be applied. - A locked filter never opens its editor or shows
FilterRemove. Enforce what it stands for where the data is read. - Never pass
asChildorrender.