Skip to content

[Due for payment 2026-09-18] label:inbox[CFI] Persist filters across views in Search #95976

Description

@JS00001

Coming from https://github.com/Expensify/Expensify/issues/651173, we'd like to make the following changes:

Background

We consistently hear feedback that users expect filters and columns to persist independently for each search view. Today, changes made in one default/suggested search are lost when navigating away and back, forcing users to repeatedly re-apply their columns and filters.

Example:

  • A user opens the Expenses view
  • They apply the filters: from:Jack workspace:Jack, Inc
  • They switch to the Reports view
  • They return to Expenses view and their filters are no longer applied

Expected behavior
The user sees the filters applied on the Expenses view (from:Jack workspace:Jack, Inc) exactly as they left it.

Solution

Let’s allow each search that appears in the LHN to maintain its own filter and column configuration. To do that, we’d make the following UI changes:

  • Replace "❌ Clear" with "🔁 Reset" in the filters bar.
  • The 'Reset' button will appear once the current view's filters differ from its default state. Clicking 'Reset' will reset the view's filters back to their original state
  • Filters that are part of a search's default filter set will not display an "x" button. This prevents users from removing 'defining' filters from a specific view. Examples of default filters include:
    • "Withdrawn" and "Withdrawal Type" on the Bank Reconciliation View
    • “Reimbursable” and “Status” filters on the Cash Accruals View
  • Display filter pills in a consistent order. We will always show default filter pills first, followed by user-added filters.

Technical Implementation

We will create a NVP named searchFilters which will store the following data structure (note: all keys are optional):

{
  "expenses": "type:expense",
  "reports": "type:report",
  "submit": "type:expense action:submit from:1234",
  "approve": "type:expense action:approve to:1234",
  "pay": "type:expense action:pay from:1234",
  "export": "type:report action:export from:1234",
  "statements": "type:report action:statements from:1234",
  "unapprovedCash": "...",
  "unapprovedCard": "...",
  "reconciliation": "...",
  "topSpenders": "...",
  "topCategories": "...",
  "topMerchants": "...",
  "spendOverTime": "...",
  "savedSearch_123456789": "...",
  "savedSearch_987654321": "...",
  "savedSearch_111111111": "...",
  "savedSearch_222222222": "...",
}
  • Update the search sidebar to not show the highlight based on hash anymore, but based on the key of the search (e.g expenses, reports, etc)
  • When we run Search, ensure that every query includes a searchKey in the jsonQuery, the BE will automatically save the changes to a new searchFilters nvp, so lets optimistically save the new query string in onyx
  • When the user navigates to a search that has a key that is not currently stored in searchFilters, lets show the default for that view (the current suggested search defaults)
  • When a user changes a filter while on a search, we will not change the search key, but rather, keep the user on the current selected search

Saved Search Updates

  • We currently key saved searches by their hash, we will no longer do this.
  • Update SaveSearch and DeleteSavedSearch to take a new savedSearchID param, which will be an optimistic rand64 value. These will be the new key for each saved search in the savedSearches nvp
  • Since hashes were previously unique (for each search a user owned), lets fallback to use that as the savedSearchID for existing suggested searches
  • All new saved searches should generate a new unique ID when saving them

Prototype

Screen.Recording.2026-07-07.at.4.22.35.PM.mov
Issue OwnerCurrent Issue Owner: @mallenexpensify

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionDailyKSv2NewFeatureSomething to build that is a new item.

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions