Repository navigation
[Due for payment 2026-10-22] Add count and spend total selectors to the Spend footer to let customers choose the data they see #99452
Description
Background
The footer bar on Spend shows a count of matching expenses, a currency selector, and a total spend amount. The count counts transactions, even on a type:expense-report search where the user is working with reports. The total is a single value, so there is no way to see spend broken out by reimbursable, non-reimbursable, billable, or non-billable.
Customers have asked to see this data in several ways: expense count versus report count, different kinds of totals, and amounts in different currencies. We support only the last one today. #673654 started on the count half before we had a pattern that covered all three.
This issue applies a more holistic pattern to the whole footer. We add a selector for the count and a selector for the spend total, and we move the existing currency selector onto the same pattern so all three behave identically. #673654 remains the backend prerequisite for the count aggregates and ships on its own.
Scope
- Add a count selector to the footer, with the options
ExpensesandReports. - Add a spend total selector to the footer, with the options
Total spend,Reimbursable,Non-reimbursable,Billable, andNon-billable. - Move the existing currency selector onto the same selector pattern, so all three use a popover with
ApplyandReset. - Return both the expense count and the report count on every search by default, so the count selector applies instantly with no round trip.
- Applying the currency or total selector retriggers the search and shows a skeleton loader on the total.
- Each selection is sticky per search type, so a choice made on
type:expense-reportresults does not carry over totype:expenseresults. - We'll time each new aggregate query during the backend PRs and post the timings in this issue before frontend work starts.
- There's no change to which rows the search returns, to the results table, or to the green
X selectedbutton; this issue changes the footer only.
Product and design details
640833541-a22a1cf2-7811-4bb1-b986-7bebe702e219.1.mp4
We'll use a display popover pattern, per the video above. All three selectors reuse it. On small screens they open in the same bottom-anchored sheet the currency selector uses today, so no new component is needed.
Count selector
Options are Expenses and Reports. The footer renders the selection as a label and a value, e.g. Expenses: 1,204 or Reports: 87.
We show the count selector always. The default follows the search type, because that matches the unit the user is working with in that context and the unit the green X selected button count:
type:expense→Expensestype:expense-report→Reports
Every search returns both counts, so switching between them is client-side. There is no re-trigger and no loading state on the count.
Spend total selector
Options appear only when at least one expense in the current search results matches:
Total spend: always listed, and the default.Reimbursable: at least one reimbursable expense in the results.Non-reimbursable: at least one non-reimbursable expense in the results.Billable: at least one billable expense in the results.Non-billable: at least one non-billable expense in the results.
Every expense is either reimbursable or non-reimbursable, so a non-empty result set always has at least two applicable options and the selector always renders. Billable and Non-billable only appear for workspaces that track billable, since expenses elsewhere have no billable value to match on.
Each option shows the summed monetary total of the matching expenses in the selected currency, not a count.
Currency selector
No change to the currency list or to how the amount is converted. The selector moves to the popover pattern above so its interaction matches the other two, and it keeps Apply and Reset.
Apply, Reset, and re-triggering the search
Each selector is its own popover with Apply and Reset. Nothing changes in the footer until the user taps Apply.
Applycloses the popover and commits the new selection. For count, the footer updates immediately from data the search already returned. For currency and total, we re-trigger the search.Resetreturns that selector to its default for the current search type: the type-based default for count,Total spendfor total, and the user's existing default for currency. The user still tapsApplyto commit it.- While a re-triggered search is in progress, the currency and total selectors are disabled, so we never have overlapping requests for the same footer. The count selector stays interactive, since it needs no request.
Selections do not change which expenses or reports match, so the results table is untouched by a footer change. Only the footer total reloads.
Loading states
While a re-triggered search is in progress:
- The total value shows a skeleton loader.
- The count value shows no loader and does not change, because both counts are already returned.
- The selector labels stay rendered, so the footer does not change height or shift as the total returns.
- The results table shows no loaders, because the result set is unchanged.
Persistence
Each of the three selections is sticky per search type. We store the count, total, and currency selections separately for type:expense and type:expense-report, and restore them when the user returns to a search of that type. A user who always wants report counts on Reports and expense counts on Expenses sets it once.
Empty state
When a search returns no results, the footer shows Total spend with a zero amount and no total selector, since no total option applies. The count selector still follows the account-level rule above and shows a zero count.
Backend changes and query timing
#673654 delivers the backend for the count half: returning the report count on type:expense-report results and on type:expense results, so every search returns both counts and the client decides which to display. If returning both by default turns out to affect query timings, #673654 adds a param to the search command instead, and we update this OP to match.
This issue's backend work adds the four new totals as aggregates on the search command. These are requested by param rather than returned by default, since there are four of them and only one is displayed at a time.
We time each new aggregate query as part of the backend PRs and post the timings in this issue. If any one of them materially slows the search, we resolve that before frontend work starts rather than shipping a footer that is slow to update.
QA Examples
- An account with both expenses and reports runs a
type:expense-reportsearch. The footer defaults toReports: 87. The user opens the count selector, choosesExpenses, and tapsApply. The footer showsExpenses: 1,204immediately, with no loader and no retriggered search. - A user changes the total from
Total spendtoReimbursableand tapsApply. The total shows a skeleton loader while the search retriggers, then renders the reimbursable total. The count value and the results table are unaffected. - An account that has expenses but has never had a report runs a
type:expensesearch. The footer shows the expense count as static text and no count selector. - An account with both runs a
type:expensesearch filtered to unreported expenses, then selectsReportsand applies. The footer showsReports: 0. This is expected, since the user filtered their way into it. - A search returns expenses that are all reimbursable, in a workspace that does not track billable. The total selector lists
Total spendandReimbursableonly. - A search returns a mix of reimbursable, non-reimbursable, and billable expenses. The total selector lists
Total spend,Reimbursable,Non-reimbursable,Billable, andNon-billable. - A user selects
Reimbursableon atype:expense-reportsearch, navigates away, and returns. The footer is still onReimbursable. They switch to atype:expensesearch and see that search type's own last selection, notReimbursable. - A user on
type:expense-reportresults has switched the count toExpenses. They open the count selector, tapReset, thenApply. The footer returns toReportsimmediately, with no retriggered search. - A search returns no results. The footer shows a zero count and
Total spendat zero, with no total selector.
Issue Owner
Current Issue Owner: @mkhutornyiMetadata
Metadata
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
JS00001 commentedon Aug 26, 2026
The BE PRs for adding report/expense count to search are merged. @Valforte could we start on the addition of the reimbursable/billable totals/counts next?
JmillsExpensify commentedon Aug 26, 2026
Woo! Super exciting.
Valforte commentedon Aug 28, 2026
@JmillsExpensify I have both BE PRs needed for it ready, let me know if there's any detail still pending on this issue or if it's ready to be worked on
JmillsExpensify commentedon Aug 29, 2026
All good here, let's keep going!
Valforte commentedon Aug 31, 2026
Here is the Search result with the new fields:
In the onyx that, under
search, the following data will be returned:@truph01 you can start working on the FE PR while we get the billable and reimbursable fields ready
50 remaining items
jponikarchuk commentedon Oct 14, 2026
Deploy Blocker #104031 was identified to be related to the PR #100674 that attempted to fix this issue.
melvin-bot commentedon Oct 14, 2026
If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.
If a regression has occurred and you are the assigned CM follow the instructions here.
If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.
truph01 commentedon Oct 15, 2026
@JS00001 @mkhutornyi I opened PR #104058 to fix these regressions except the #104030 - which I think it is expected.
JS00001 commentedon Oct 15, 2026
I pinged tom to ask, lets see what he thinks. I could see this going either way
[-]Add count and spend total selectors to the Spend footer to let customers choose the data they see[/-][+][Due for payment 2026-10-22] Add count and spend total selectors to the Spend footer to let customers choose the data they see[/+]melvin-bot commentedon Oct 15, 2026
@mkhutornyi / @truph01
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.9-4 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:
If no regressions arise, payment will be issued on 2026-10-22. 🎊
The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]. If no checklist is needed for this issue, you can click: [no checklist button]
melvin-bot commentedon Oct 20, 2026
@mkhutornyi Eep! 4 days overdue now. Issues have feelings too...
JmillsExpensify commentedon Oct 21, 2026
In the regression preiod