Background
When admins narrow down expenses on the Spend page, they might want to express an exclusion rather than an inclusion: "show me everything that isn't on Adventure Inc," "everything that doesn't have a receipt," "every merchant except Big Buy Supply." Today the filter UI only lets users build positive matches, so to answer an exclusion question they have to either reason in reverse (select every value they do want) or drop into raw search syntax. Both are slow, and the second is invisible to most users.
The good news is that negation is already supported by search. This is purely a front-end initiative: we're exposing a control that lets users build a negated filter from the UI, and reflecting that negation in the resulting filter chip. Nothing about the underlying search syntax or back end changes.
We use is not for value-based filters (Merchant, Workspace, etc.) and doesn't have for presence-based filters (the Has filter), because that's the language that reads naturally for each filter type — you say a merchant "is not" something, but a receipt is something an expense "doesn't have."
The full Figma file for this initiative can be found here.
Scope
- Add a negation toggle to the filter configuration UI for the supported filters only. No new search capability — negation already works in search syntax.
- This is front-end only. No changes to search syntax, query parsing, or the back end.
- Supported filters in this release: To, From, Has, Workspace, Status, Currency, Purchase currency, Merchant, Exported to. These are where we're seeing customer demand. Other filters keep their current behavior and can be added later.
- Reflect the negated state in the filter chip label.
Product and design details
Negation toggle
Each supported filter's configuration surface gains a segmented toggle at the top that flips the filter between its positive and negated form:
- Value-based filters (To, From, Workspace, Status, Currency, Purchase currency, Merchant, Exported to) use an is / is not toggle.
- Presence-based filters (Has) use a has / doesn't have toggle.
The toggle defaults to the positive option (is / has). The user picks their value(s) as they do today; the only addition is the toggle that determines whether the selection is matched or excluded.
Filter chip
The chip that appears in the filter bar reflects the negation:
- Positive:
Has: Receipt, Merchant is: Big Buy Supply, Workspace is: Adventure Inc
- Negated:
Doesn't have: Receipt, Merchant is not: Big Buy Supply, Workspace is not: Adventure Inc
Each chip retains its existing dropdown caret (to reopen and reconfigure, including flipping the toggle) and its individual remove (×) affordance. The global Clear action continues to clear all filters.
Combining filters
Negated filters combine with other filters exactly as positive ones do today. For example, Doesn't have: Receipt + Workspace is not: Adventure Inc returns expenses that both lack a receipt and are not on Adventure Inc. There is no special interaction between negation and combination — a negated filter is just another active filter.
Examples
- A user opens the Has filter, leaves the toggle on doesn't have, and checks Receipt. The chip reads
Doesn't have: Receipt and the list shows only expenses without a receipt.
- A user opens the Merchant filter, flips the toggle to is not, and selects Big Buy Supply. The chip reads
Merchant is not: Big Buy Supply and the list excludes those expenses.
- A user applies
Doesn't have: Receipt, then adds a Workspace filter set to is not: Adventure Inc. Both chips appear, and the list reflects both exclusions.
- A user reopens a negated chip via its caret and flips the toggle back to is / has; the chip and results update to the positive form.
Issue Owner
Current Issue Owner: @JS00001
Background
When admins narrow down expenses on the Spend page, they might want to express an exclusion rather than an inclusion: "show me everything that isn't on Adventure Inc," "everything that doesn't have a receipt," "every merchant except Big Buy Supply." Today the filter UI only lets users build positive matches, so to answer an exclusion question they have to either reason in reverse (select every value they do want) or drop into raw search syntax. Both are slow, and the second is invisible to most users.
The good news is that negation is already supported by search. This is purely a front-end initiative: we're exposing a control that lets users build a negated filter from the UI, and reflecting that negation in the resulting filter chip. Nothing about the underlying search syntax or back end changes.
We use is not for value-based filters (Merchant, Workspace, etc.) and doesn't have for presence-based filters (the Has filter), because that's the language that reads naturally for each filter type — you say a merchant "is not" something, but a receipt is something an expense "doesn't have."
The full Figma file for this initiative can be found here.
Scope
Product and design details
Negation toggle
Each supported filter's configuration surface gains a segmented toggle at the top that flips the filter between its positive and negated form:
The toggle defaults to the positive option (is / has). The user picks their value(s) as they do today; the only addition is the toggle that determines whether the selection is matched or excluded.
Filter chip
The chip that appears in the filter bar reflects the negation:
Has: Receipt,Merchant is: Big Buy Supply,Workspace is: Adventure IncDoesn't have: Receipt,Merchant is not: Big Buy Supply,Workspace is not: Adventure IncEach chip retains its existing dropdown caret (to reopen and reconfigure, including flipping the toggle) and its individual remove (×) affordance. The global Clear action continues to clear all filters.
Combining filters
Negated filters combine with other filters exactly as positive ones do today. For example,
Doesn't have: Receipt+Workspace is not: Adventure Increturns expenses that both lack a receipt and are not on Adventure Inc. There is no special interaction between negation and combination — a negated filter is just another active filter.Examples
Doesn't have: Receiptand the list shows only expenses without a receipt.Merchant is not: Big Buy Supplyand the list excludes those expenses.Doesn't have: Receipt, then adds a Workspace filter set to is not: Adventure Inc. Both chips appear, and the list reflects both exclusions.Issue Owner
Current Issue Owner: @JS00001