Skip to main content
Nexus Design System
GitHub

Filtering

Build filters for a list from ChoiceFilter, FilterBuilder and the other filter blocks and components. Keep the results and every active filter visible, and make each filter easy to edit or clear. Start with two decisions: when a change applies, and whether filters can be grouped.

1. Decide when a change applies

TimingUse it whenBuild it withExample
ImmediatelyEach choice is complete, easy to undo and cheap to apply, such as picking one status.ChoiceFilterTeam directory example
Per filter, on ApplyOne condition needs several inputs or a review first, such as a range, a date span or several checked values.MultiChoiceFilter, TextFilter, NumberComparisonFilter, NumberRangeFilter, DateRangeFilterInvoice list example
Whole set, on one ApplySeveral conditions are edited together and results should change only once, such as a grouped query.FilterBuilder, with draft and applied stateGrouped conditions example

Choose the timing by how the filter is used, not by its field type. Closing a filter never applies it. Cancel, Escape and clicking outside all discard the draft (the edits not yet applied).

Changing the operator applies at once, unless the new operator needs a value first. If a panel has its own Apply button, pass the panel’s draft to each filter. Don’t add a second Apply inside it.

2. Decide flat or grouped

With flat filters, every condition must match. An All group matches when every condition in it matches, and an Any group matches when at least one does. Use groups only when people need a query like “Active members who are in Design or have more than three projects”.

Build grouped queries with FilterBuilder. Keep the query as a draft until it’s applied, so results don’t change mid-edit.

Grouped conditions

Team members

Filter your team by status, team or activity.

Match
conditions
Match
conditions

Matching members

2 of 5 members
NameStatusTeamProjects
Priya Shahactivedesign2
Maya Chenactiveengineering6
View applied filter data
{
  "kind": "group",
  "id": "root",
  "conjunction": "all",
  "children": [
    {
      "kind": "rule",
      "id": "status-rule",
      "field": "status",
      "operator": "is",
      "value": "active"
    },
    {
      "kind": "group",
      "id": "team-group",
      "conjunction": "any",
      "children": [
        {
          "kind": "rule",
          "id": "team-rule",
          "field": "team",
          "operator": "is",
          "value": "design"
        },
        {
          "kind": "rule",
          "id": "projects-rule",
          "field": "projects",
          "operator": "greaterThan",
          "value": "3"
        }
      ]
    }
  ]
}

To move from quick filters to a grouped query, convert each block’s value into one FilterBuilder rule. Each block’s example file exports its own conversion. FilterBuilder doesn’t re-check a block’s number limits.

Match
conditions

3. Start from a minimal example

Each block page starts with a minimal example and the files to copy:

Lay several filters out with blocks/filtering/applied-filters.tsx. It wraps filters onto new lines as needed, and holds no filter state. If filters are edited in a separate panel, show the applied ones as removable chips:

Invoice filters

Choose conditions in Filters. The chips below keep the applied conditions visible after the menu closes. Click a chip to remove that condition.

Applied filters:

Showing paid invoices from India.

4. Show the result states

Keep active filters visible while results load or fail. Show a different message for an empty list, no matches and a failed request. Retry keeps the filters.

Show the total count across all pages, and go back to page one when a filter changes. The result-state examples use native inputs, but the same states apply to the blocks.

Loading

Team members

Find people across your teams.

Loading members…

Empty collection

Team members

Find people across your teams.

0 members

No members yet

Invite people to your teams to see them here.

No matches

Team members

Find people across your teams.

0 members

No matching members

Try another name or clear the filters.

Failure and retry

Team members

Find people across your teams.

Members unavailable

Examples

Team directory: immediate updates

Choosing a status or team updates the table at once. The filters have no Apply button.

Team members

Find people across your teams.

6 of 6 members

Matching team members
NameTeamStatusProjects
Priya Shah

Design

DesignActive2
Alex Morgan

Engineering

EngineeringActive6
Maya Chen

Design

DesignInvited0
Sam Rivera

Operations

OperationsActive4
Noor Ahmed

Engineering

EngineeringInvited1
Leo Martin

Design

DesignActive5

Invoice list: Apply per filter

Each filter opens a checklist with its own Apply button. The trigger shows the applied values. Escape or clicking outside discards the changes.

Invoices

Track payments and find invoices that need your attention.

6 of 6 invoices

CustomerInvoiceStatusIssuedAmount
Acme Studio
India
INV-1048Paid24 Sep 2026₹48,000
Northstar Labs
United States
INV-1047Open23 Sep 2026₹1,25,000
Forma Design
United Kingdom
INV-1046Paid22 Sep 2026₹72,000
Common Ground
India
INV-1045Overdue18 Sep 2026₹36,000
Acme Studio
India
INV-1044Open16 Sep 2026₹24,000
Fieldwork
United States
INV-1043Paid15 Sep 2026₹96,000

These examples use sample data. The filtering blocks are experimental, so test them with your own data before you ship.

What your app owns

Your app owns the fields, permissions, values, filtering logic, requests, pagination and URL state. Cancel outdated requests and ignore late responses in your data layer.

Where to go next

  • Components: FilterChip for a removal-only summary, FilterCondition for independently editable parts, FilterBuilder for grouped conditions.
  • The source lives in packages/react/src/blocks/filtering and packages/react/src/patterns/filtering.