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.