Components / Filter Menu

Filter Menu

A toolbar filter over SEVERAL values at once: account types, statuses, platforms. One value only? Use Select. A control strip that changes a mode rather than narrowing a list? That is not a filter.

import { FilterMenu } from '@layers/ui/filter-menu'

Rendered stock

House rules

  • Stock shadcn structure: DropdownMenu + DropdownMenuCheckboxItem, which is the documented pattern for toggling many options. Select commits to one value and closes; ToggleGroup is a control strip, not a filter (rules.md: several options at once → checkboxes).
  • ALL-SELECTED is the default and means "no filter". A filter that starts narrow shows the user an empty surface and makes them opt IN to seeing their own data. Defaulting wide also kills a whole class of dead state: filtering to one platform can no longer say "nothing here" just because the rows that exist are of a type the filter happened to exclude.
  • The last selected value cannot be unchecked. An empty selection is a filter that can only ever match nothing, which reads as a broken surface rather than as a filter.
  • The trigger summarises: "All", the single label when one is picked, else "N selected". Never list the selected labels — three labels wrap, and a toolbar is exactly one line.
  • The menu stays open while you pick (closeOnClick={false}). Picking several values is the point; a menu that closes per click makes the user reopen it N times.
  • All-selected clears the URL param rather than persisting a no-op, so a shared link carries a scope only when one is actually set.
  • Pair it with EmptyState’s `filtered` prop and DataTable’s `filtered` prop. The filter narrows; those two are what tell the user why rows are missing and how to get them back.