Anatomy
┌─────────────────────────────────────────────────────────────┐
│ Status ▾ Owner ▾ Date ▾ 42 of 318 invoices │
│ ● Overdue ✕ ● Owner: Dana ✕ Clear all │
└─────────────────────────────────────────────────────────────┘
↑ active filters, visible and individually removable
The controls are the easy half. The three that matter:
- Chips for what is on. The single most common failure is a filter applied from a dropdown that then shows no trace of itself. People read a partial list as if it were the whole one and draw wrong conclusions.
- State in the URL. It makes the view shareable, reloadable and — the part people feel every day — restorable when they come back from a record.
- A count. "42 of 318" is orientation: it says both how much you have and how much you excluded.
Why it works
It serves a different question from search. Search answers where is this specific thing; filters answer which of these things match a description. A product that offers only one of the two leaves half its users scanning.
Chips are what make it safe. A filtered list looks exactly like an unfiltered one, so the interface has to say which it is — otherwise the person who inherited someone else's saved link reports a data problem that is really a filter.
Putting the state in the URL is the quiet upgrade. It turns a transient UI state into something a person can send in a message, which is how most real collaboration on a list actually happens.
Getting it wrong
- Invisible active filters. The list is wrong and nothing on screen says so.
- A filter per column. Filters are a shared cost: everyone reads them, few use each one. Add the ones people ask for, not the ones the schema permits.
- Filter state only in memory. Reload, or come back from a record, and the work is gone — see back link.
- A bare empty state. "No results" with active filters and no way to clear them is a dead end.
- A hidden default. A list quietly scoped to this month, with nothing saying so, produces confident wrong answers.
Exemplars
Linear's filter bar builds up as chips, each one editable in place, and the whole set is one click from being saved as a view. It shows the natural progression: filters that keep getting rebuilt want a name.
Stripe's payments filters are notable for restraint — a handful of attributes on a record type with dozens of fields — and for putting everything in the URL, so support conversations happen by pasting a filtered link.
The extractable rule: a filter bar's job is to make the current scope undeniable. Narrowing the list is the easy part; saying so, permanently and visibly, is what keeps people from misreading it.