Skip to content

[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

Open

Description

@JmillsExpensify

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 Expenses and Reports.
  • Add a spend total selector to the footer, with the options Total spend, Reimbursable, Non-reimbursable, Billable, and Non-billable.
  • Move the existing currency selector onto the same selector pattern, so all three use a popover with Apply and Reset.
  • 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-report results does not carry over to type:expense results.
  • 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 selected button; 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.

Image Image Image

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 → Expenses
  • type: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.

  • Apply closes 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.
  • Reset returns that selector to its default for the current search type: the type-based default for count, Total spend for total, and the user's existing default for currency. The user still taps Apply to 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-report search. The footer defaults to Reports: 87. The user opens the count selector, chooses Expenses, and taps Apply. The footer shows Expenses: 1,204 immediately, with no loader and no retriggered search.
  • A user changes the total from Total spend to Reimbursable and taps Apply. 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:expense search. The footer shows the expense count as static text and no count selector.
  • An account with both runs a type:expense search filtered to unreported expenses, then selects Reports and applies. The footer shows Reports: 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 spend and Reimbursable only.
  • A search returns a mix of reimbursable, non-reimbursable, and billable expenses. The total selector lists Total spend, Reimbursable, Non-reimbursable, Billable, and Non-billable.
  • A user selects Reimbursable on a type:expense-report search, navigates away, and returns. The footer is still on Reimbursable. They switch to a type:expense search and see that search type's own last selection, not Reimbursable.
  • A user on type:expense-report results has switched the count to Expenses. They open the count selector, tap Reset, then Apply. The footer returns to Reports immediately, with no retriggered search.
  • A search returns no results. The footer shows a zero count and Total spend at zero, with no total selector.
Issue OwnerCurrent Issue Owner: @mkhutornyi

Activity

  1. added
    ImprovementItem broken or needs improvement.
    InternalRequires API changes or must be handled by Expensify staff
    on Aug 25, 2026
  2. JS00001 commented on Aug 26, 2026

    @JS00001
    Contributor

    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?

  3. JmillsExpensify commented on Aug 26, 2026

    @JmillsExpensify
    ContributorAuthor

    Woo! Super exciting.

  4. Valforte commented on Aug 28, 2026

    @Valforte
    Contributor

    @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

  5. JmillsExpensify commented on Aug 29, 2026

    @JmillsExpensify
    ContributorAuthor

    All good here, let's keep going!

  6. Valforte commented on Aug 31, 2026

    @Valforte
    Contributor

    Here is the Search result with the new fields:
    In the onyx that, under search, the following data will be returned:

    --- PR pending:
    billableTotal
    nonBillableTotal
    nonReimbursableTotal
    reimbursableTotal
    
    --- Already present:
    count - count of expenses
    reportCount - count of reports
    total - total amount
    currency - selected currency
    
    Image

    @truph01 you can start working on the FE PR while we get the billable and reimbursable fields ready

  7. 50 remaining items

  8. jponikarchuk commented on Oct 14, 2026

    @jponikarchuk

    Deploy Blocker #104031 was identified to be related to the PR #100674 that attempted to fix this issue.

  9. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    ⚠️ Looks like this issue was linked to a Deploy Blocker here

    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.

  10. truph01 commented on Oct 15, 2026

    @truph01
    Contributor

    @truph01 can we create a follow up PR to remove the beta, and fix these two issues?
    #104014 - Lets fix this
    #104010 - Lets fix this
    #104026 - Lets fix this
    #104030 - Lets fix this
    #104031 - Lets fix thsi

    @JS00001 @mkhutornyi I opened PR #104058 to fix these regressions except the #104030 - which I think it is expected.

  11. JS00001 commented on Oct 15, 2026

    @JS00001
    Contributor

    I pinged tom to ask, lets see what he thinks. I could see this going either way

  12. changed the title [-]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[/+] on Oct 15, 2026
  13. melvin-bot commented on Oct 15, 2026

    @melvin-bot

    @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]

  14. melvin-bot commented on Oct 20, 2026

    @melvin-bot

    @mkhutornyi Eep! 4 days overdue now. Issues have feelings too...

  15. JmillsExpensify commented on Oct 21, 2026

    @JmillsExpensify
    ContributorAuthor

    In the regression preiod

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

Metadata

Metadata

Labels

DailyKSv2ImprovementItem broken or needs improvement.InternalRequires API changes or must be handled by Expensify staff

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions