Skip to content
Statecraft

All patterns

  • Bulk Actions

    Let users perform one action across many records safely, with clear scope, eligibility and recovery.

    Data
  • Advanced Filters

    Help users narrow large datasets with filters they can see, edit, share and recover from.

    Data
  • Autosave

    Save changes continuously without a Save button, while keeping users certain their work is safe.

    Forms
  • Approval Workflow

    Route a request through one or more reviewers with clear status, accountability and an auditable history.

    Workflow
  • AI Response

    Present generated answers with streaming, sources, control and recovery, so users can trust and verify them.

    AI
  • File Upload

    Let users add files with visible progress, early validation and recovery that never loses what already uploaded.

    Files
  • Command Palette

    Give users one keyboard-first entry point to jump anywhere and run any action without hunting through menus.

    Navigation
  • Subscription Management

    Let customers upgrade, downgrade, change billing cycles and cancel with exact prices, dates and consequences shown before they confirm.

    Payments
  • Refunds

    Let support staff or customers return money with the exact amount, destination, timing and consequences stated before it's irreversible.

    Payments
  • Checkout

    Take a customer from plan choice to paid with the fewest fields, a total that never surprises, and errors that keep what they typed.

    Payments
  • Failed Payment Recovery

    Recover failed renewals with timely, specific prompts and a grace period, before customers lose access they still want.

    Payments
  • Usage & Limits

    Show customers how much of their plan they've used and handle the moment they hit a limit without breaking their work.

    Payments
  • App Sidebar

    Organise a product's main navigation so users always know where they are, reach frequent places in one click, and keep their place on small screens.

    Navigation
  • Tabs

    Split one object's content into peer views that users switch between without losing their place, state or URL.

    Navigation
  • Breadcrumbs & Back

    Show users where they are in a hierarchy and get them back to exactly where they came from — filters, scroll and all.

    Navigation
  • File Preview

    Let users look inside a file without downloading it, with a predictable fallback for every type the product can't render.

    Files
  • Attachments

    Attach files to records and comments with clear ownership, visibility and deletion rules that match the record they belong to.

    Files
  • CSV Import

    Bring spreadsheet data into the product with column mapping, row-level validation and a preview, so nothing is imported by surprise.

    Files
  • Confirmation

    Ask for confirmation only when an action is hard to undo, and make the dialog state exactly what will happen.

    Workflow
  • Partial Failure

    Report operations where some items succeed and some fail, so users know exactly what happened and what to do about the rest.

    Workflow
  • Permissions

    Show people what they can do, explain what they can't, and give them a way forward instead of a dead end.

    Workflow
  • Notifications

    Tell people about things that need them, in the right channel and at the right volume, without burying what matters.

    Workflow
  • Activity History

    Show who changed what and when on a record, in a timeline people can scan, filter and trust.

    Data
  • Empty States

    Design what users see when there's nothing to show, so every empty screen explains why and offers the next useful step.

    Data
  • Version History

    Let users see earlier versions of a document or record, compare them, and restore safely without losing current work.

    Forms
  • Human Review

    Put a person between AI output and real-world consequences, with review that's fast for good output and careful for risky output.

    AI
  • Feedback

    Collect quick, specific feedback on AI output that users actually give, and that the team can actually use.

    AI
  • Inline Validation

    Tell users about input problems at the right moment — not while they're still typing, and not only after they submit.

    Forms
  • Unsaved Changes

    Protect work in forms that save explicitly, warning only when something would actually be lost.

    Forms
  • Offline Mode

    Keep users working when the connection drops, with an honest view of what's synced, what's pending and what can't be done offline.

    Forms
  • Pagination

    Split long lists into pages or progressive loads in a way that keeps position, counts and selection predictable.

    Data
  • Saved Views

    Let users save a combination of filters, sorting and columns as a named view they and their team can return to.

    Data
  • Comments

    Let people discuss work where it happens — on the record or the exact part of it — with mentions, threads and resolution.

    Workflow
  • Error Recovery

    When something fails, say what happened in plain language, protect the user's work, and offer the most useful next step.

    Workflow
  • Keyboard Shortcuts

    Give frequent users fast keyboard paths that are discoverable, consistent and never get in the way of typing.

    Navigation
  • Prompt Input

    Design the box where users ask AI for things — with context, attachments and controls visible — so prompts start strong and never get lost.

    AI
  • AI Suggestions

    Offer AI-generated values, completions and next steps inline, so users accept good ones in one action and ignore the rest at no cost.

    AI
  • Agent Progress

    Show what an AI agent is doing during long, multi-step tasks — steps, tool use and decisions — so users can follow, steer and stop it.

    AI
  • AI Onboarding

    Introduce an AI feature by showing what it can do with the user's own data, setting honest expectations about limits and privacy.

    AI
  • Export

    Let users take their data out in the format they need, with a clear scope and no surprises about what's included.

    Files
  • Storage Limits

    Show how much storage is used and by what, and handle a full quota without blocking work or deleting anything.

    Files
DataFree

Advanced Filters

Help users narrow large datasets with filters they can see, edit, share and recover from.

8 states7 edge casesDesktop + Mobile

01The problem

Users need to find a specific slice of a large dataset — overdue invoices over $5,000 from EU customers, for example. Simple dropdowns don't scale to this, but a query builder overwhelms people who only ever filter by status. The interface has to serve both without hiding which filters are currently shaping the results.

02When to use

Use when

  • Lists with hundreds or more records and several filterable attributes
  • Users return to the same slices repeatedly (“my open tickets”, “overdue this month”)
  • Filtered views need to be shared with teammates by link
  • Filters combine across different field types — status, date range, amount, owner

Avoid when

  • The list has fewer than ~50 items — search alone is faster.
  • There is only one meaningful attribute to filter by; use tabs or a segmented control.
  • Users need arbitrary boolean logic (nested AND/OR). That is a query builder, a different pattern.

03Recommended UX

Statecraft recommendation

Show the two or three most-used filters inline above the results and put everything else behind a single “Filters” control. Every active filter, wherever it was set, must appear as a removable chip in one applied-filters row.

Usage on most filterable lists is heavily skewed: status and date account for the majority of filtering. Promoting them inline makes the common case one click.

The applied-filters row is the single source of truth for why the list looks the way it does. Users should never have to open a panel to discover a hidden filter.

Separating “where you set a filter” from “where you see active filters” lets the panel stay large and structured while the chips stay compact.

04Interaction flow

  1. 01

    Unfiltered list

    Quick filters inline, total count visible.

  2. 02

    Apply quick filter

    Results update immediately; chip appears.

  3. 03

    Open filter panel

    Side panel on desktop, full-height drawer on mobile.

  4. 04

    Compose filters

    Panel shows a live result count before applying.

  5. 05

    Apply

    Chips summarise every active filter; URL updates.

  6. 06

    Refine or save

    Remove a chip, Clear all, or Save as view.

  7. Result

    • Results
    • Zero results
    • Error

05Desktop behaviour

Desktop has room for inline quick filters and a persistent applied-filters row. The full panel opens beside the results so users can see the list respond.

Desktop rules

  • Quick filters apply instantly. Panel filters can apply instantly too if results return in under ~300ms; otherwise use an Apply button.
  • Show a count badge on the Filters button when panel filters are active: “Filters · 3”.
  • Chips read as sentences: “Amount > $5,000”, not “amount: gt 5000”.
  • Place “Clear all” at the end of the chip row, not inside the panel only.
Frequent filters stay inline. Everything else lives behind Filters. Every active filter appears in one chip row with Clear all.

06Mobile behaviour

On mobile there's no room for inline dropdowns and a side panel. Filtering becomes a deliberate, full-screen task with an explicit Apply step.

Mobile rules

  • Collapse all filters into one “Filters” button with an active count.
  • Open a full-height drawer with grouped filters and a sticky footer: “Clear” and “Show 42 results”.
  • Apply only when the user taps the footer button — live-updating a hidden list wastes data and causes jank.
  • Keep the chip row below the search field; let it wrap rather than scroll horizontally.
A full-height drawer with grouped filters. Nothing applies until the user taps the footer, which states the result count.

07States

  • Unfiltered

    Quick filters at default. Total count visible: “1,284 invoices”.

  • Filter open

    Dropdown or panel open, with option counts where cheap to compute.

  • Filtered

    Chips visible, count updated: “42 of 1,284 invoices”.

  • Loading results

    Keep the previous results visible but dimmed; avoid a blank table between filters.

  • Zero results

    Explains which filters caused it and offers to remove the most restrictive one.

  • Invalid combination

    Conflicting values are blocked at input, e.g. an end date before the start date.

  • Saved view active

    View name shown; edits mark it as “Edited” with Save and Revert options.

  • Error

    Filters stay applied; results area shows a retry. Never silently drop filters on error.

08Edge cases

  1. EC-01

    Zero results

    The user stacks five filters and nothing matches.

    Recommendation

    Name the filters and offer the cheapest recovery: “No invoices match these 5 filters. Remove ‘Region: EU’ to see 18 results.” A generic empty illustration is a dead end.

  2. EC-02

    Filter from a shared link no longer valid

    A teammate shares a link filtered by an owner who has since been deactivated.

    Recommendation

    Keep the filter, mark the chip as unavailable (“Owner: Sam (deactivated)”), and still apply it. Silently dropping it shows the recipient a different list than the sender intended.

  3. EC-03

    Conflicting filters

    The user sets Status = Paid and Due date = overdue.

    Recommendation

    Allow it — it's valid, just empty. Reserve blocking for logically impossible input, such as a date range where the end precedes the start.

  4. EC-04

    Filters + selection

    The user has selected rows for a bulk action, then changes a filter.

    Recommendation

    Clear the selection and say so. Acting on records that no longer match the visible list is a common source of irreversible mistakes.

  5. EC-05

    Edited saved view

    The user opens “Overdue EU” and adds an amount filter.

    Recommendation

    Mark the view as edited and offer “Save” and “Save as new view”. Never auto-save changes into a shared view.

  6. EC-06

    Back button

    The user applies three filters, opens a record, then presses Back.

    Recommendation

    Restore the exact filtered list and scroll position from the URL. Losing filters on Back is one of the most reported frustrations on data-heavy products.

  7. EC-07

    Option lists with thousands of values

    Filtering by customer when there are 8,000 customers.

    Recommendation

    Use a searchable combobox that queries the server, and show recently used values first. Never render the full list.

09Microcopy

  • Result count

    Avoid

    “Showing results”

    Prefer

    “42 of 1,284 invoices”

  • Zero results

    Avoid

    “No data”

    Prefer

    “No invoices match these filters. Remove ‘Region: EU’ to see 18 results.”

  • Mobile apply button

    Avoid

    “Apply”

    Prefer

    “Show 42 results”

  • Chip label

    Avoid

    “amount: gt 5000”

    Prefer

    “Amount > $5,000”

  • Edited view

    Prefer

    “Overdue EU · Edited — Save · Revert”

10Accessibility

  • Announce result count changes in a polite live region, e.g. “42 results”.
  • Each chip's remove button needs a full label: “Remove filter Amount greater than $5,000”.
  • When a chip is removed, move focus to the next chip, or to the Filters button if none remain.
  • The mobile drawer is a modal dialog: trap focus, label it, and return focus to the Filters button on close.
  • Date range inputs must accept typed dates, not only a calendar picker.

11Developer notes

  1. 01

    Treat the URL as the source of truth for filter state. Serialise filters into query parameters so links, Back and refresh all work.

  2. 02

    Represent filters as typed objects ({ field, operator, value }) and generate chip labels from them. Don't store display strings.

  3. 03

    Debounce text inputs (~250ms) but apply discrete controls such as checkboxes immediately.

  4. 04

    Cancel in-flight requests when filters change, or late responses will overwrite newer results.

  5. 05

    Saved views should store the filter objects, not a URL string, so they survive schema changes.

12Implementation prompt

For Claude Code, Codex or Cursor

Implement an advanced filtering system for the existing list view.

Requirements:
- Two or three quick filters inline above the list (status and date range by default).
- A "Filters" button opening a side panel (desktop) or full-height drawer (mobile) with all other filters.
- Filters button shows the number of active panel filters.
- One applied-filters row showing every active filter as a removable chip, with readable labels ("Amount > $5,000").
- "Clear all" at the end of the chip row.
- Result count: "42 of 1,284 invoices", announced via a polite live region.
- URL is the source of truth: serialise filters to query params; restore on load, refresh and Back.
- Typed filter model: { field, operator, value }. Chip labels derived from the model.
- Keep previous results visible but dimmed while loading; cancel stale requests.
- Zero-results state that names the active filters and suggests removing the most restrictive one.
- Block impossible input (end date before start date) at the input.
- Saved views: save, apply, mark as edited, save as new, revert.
- Mobile drawer: sticky footer with "Clear" and "Show N results"; apply only on tap.
- Clear any active row selection when filters change, with a short notice.

Do not redesign the existing interface.
Keep filter state logic separate from presentation.

React + TypeScript reference code for this pattern — logic, hook, component and tests — is included in Statecraft Pro.