Design system

Filters

Filter and group chips for a report, and the menu that edits one filter: operator, value and empty values.

import { FilterChip, FilterMenu, OperatorList, describeFilterValue } from "@/ui";

These match the Figma ↪ Filters page: Report Chips, Operators, Value Dropdown and Filter Menu. A report shows its filters and groupings as chips. Clicking a filter chip opens a FilterMenu under it, where people pick an operator and a value, then Apply.

Try it

Click a chip to edit it, × to remove it, or add a filter. Apply updates the chip, and Cancel on a new filter drops it.

<FilterChip
  field="Industry"
  operator={filter.operator}
  value={describeFilterValue(filter)}
  selected={open}
  onClick={toggle}
  onRemove={remove}
/>
{open && (
  <FilterMenu field="Industry" type="enum" options={industries} value={filter} onApply={save} onCancel={close} />
)}

Chips

A filter chip shows a funnel, the field, the operator's symbol and the value in grey. A group chip shows a stacked-cards icon and the field. Hover shows the whole filter in a tooltip, since long values are cut off. The remove button tints and says "Remove" on hover. selected draws a blue border while the chip's menu is open.

<FilterChip field="Industry" operator="equals" value="Technology" onRemove={remove} />
<FilterChip type="group" field="Account Category" onRemove={remove} />
Figma stateIn code
RestWhite, 1px Grey 100 border
HoverPrimary 50 fill, tooltip with the whole filter
RemovePrimary 100 behind the ×, "Remove" tooltip
Selectedselected: white with a Primary 500 border

Operators

Each data type has its own operators. The list shows a radio, the operator's symbol and its name, and scrolls after five rows.

TypeOperators
multipicklistall, any, not in, is null, is not null
enumin, not in, contains, starts with, ends with, is null, is not null
booleanequals, not equals, is null, is not null
numberequals, not equals, greater or equal, less or equal, greater than, less than, is null, is not null, in, not in, between
stringin, not in, contains, does not contain, starts with, ends with, is null, is not null
dateequals, not equals, is null, is not null, between

The symbols are the SVGs from Figma, kept in Filters/icons. Our Phosphor version (2.0.15) does not have the math icons. Equals and is null use Phosphor's Equals and NumberZero.

Figma spells one operator "does not contains". Code says "does not contain".

Filter menu

The field changes with the type and the operator. Pick a field below and try each operator.

Operator takesValue field
One value (text, number)A text input, "Enter value". Enter applies.
Several (in, not in)Type a value and press Enter to add it as a tag; Backspace removes the last one. This is Figma's Multivalue state.
Two (between)From and To inputs, with a light blue underline on the one in focus.
A pick (enum, multipicklist)"Select value" opens a list with All and a checkbox per option. All shows a dash when some are picked.
True or false (boolean)"Select value" opens True and False as radios.
A date"Select date" opens the date list, grouped into Custom, Calendar Year, Fiscal Year, Fiscal Quarter, Calendar Month, Calendar Week and Calendar Days. Date, Before (Date) and After (Date) open the Date picker. Equals also offers Before and After.
Two dates (between)"Start date — End date" opens a two-month range picker.
Nothing (is null, is not null)No value. Apply works straight away.

Apply stays disabled until the filter is complete. For a number field, anything that is not a number turns the field red and shows "Invalid input. Please enter numbers only."

Figma does not show how to enter the N in presets like "Last N Days", or how to pick a year, quarter or month for Year, Quarter Year and Month Year. In code, these presets are saved by name only for now.

Anatomy

PartSpec
Chip6px 10px padding, 8px radius, 4px gaps, 14px text. Icons 12px in 20px boxes
List220px for operators, 300px for values, 320px for dates. 46px rows, shadow 0 8px 24px at 10%
Menu500px, 8px radius, shadow 0 8px 12px at 10%
TitleModify {field}, 16px medium, 6px 12px 0 padding
Field42px, 1px Grey 200 border (Primary 500 when open, red on error), 8px radius, 10px 16px padding including the border. 20px operator symbol and caret, a 20px divider, then the value in 14px
TagsPrimary 100, 2px 10px padding, 8px radius, 14px text, 12px ×
Footer"Include Empty Values" (12px, with a help icon) on the left, Cancel and Apply (sm) on the right, 12px apart

Figma uses 10px for the date group labels and the footer buttons. Code uses 12px, because 12px is the smallest text in the product.

Props

FilterChip

PropTypeDefaultNotes
type"filter" | "group""filter"
fieldstring
operatoroperator id"equals"Filter only.
valuestringUse describeFilterValue(filter).
selectedbooleanfalse
onClick, onRemovefunctionNo onRemove, no ×.

FilterMenu

PropTypeDefaultNotes
fieldstring
type"string" | "number" | "enum" | "multipicklist" | "boolean" | "date""string"
optionsstring[][]For enum and multipicklist.
value{ operator, values, includeEmpty }The applied filter.
onApplyfunctionGets { operator, values, includeEmpty }.
onCancelfunction

OperatorList: type, value, onChange.

describeFilterValue({ operator, values }) returns the chip text: one or two values joined, "Technology +2" for more, "10000 – 50000" for between, and nothing for is null.

Accessibility

  • The chip is two buttons: the chip itself (aria-expanded while its menu is open) and Remove, labelled with the whole filter.
  • The operator button is labelled with the current operator, such as "Operator: in". Lists are listboxes with aria-selected.
  • Escape or a click outside closes an open list without closing the menu.
  • The number error is announced as an alert.

On this page