You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-09-10] Export: when only one option is available, open directly into it instead of showing an intermediate menu #98779
On the Spend page (and other pages with an export flow), selecting the export entry point typically opens a menu of available export options. However, when Export is the only option in the More menu and there is only one export option available, we skip both menus and open that option directly. This can be confusing because the user loses the context that they’re entering an export flow and may not understand what the option they’ve landed on represents.
Proposed solution
When only one option is available, open the flow one level deeper instead of two. In this example, that means opening the Export menu directly and displaying the single available option, rather than navigating straight to that option.
Context
Related, already-shipped work: #94056 (standardized the export filename and renamed the export option).
The Search/Spend "More" menu deliberately collapses the Export flow whenever exactly one export option is available. In useSearchBulkActions.ts:2085-2108, when getExportOptions() returns a single item, the code builds the Export entry as a flat button that runs that option's onSelected directly (no subMenuItems) instead of the normal entry that opens the Export submenu:
Root-cause code
constsubMenuItems=getExportOptions();constsingleExportSubMenuItem=subMenuItems.length===1 ? subMenuItems.at(0) : undefined;constexportButtonOption=singleExportSubMenuItem
? {// collapsed: flat button, no subMenuItems -> runs the single option directlyicon: expensifyIcons.Export,text: singleExportSubMenuItem.text,onSelected: ()=>singleExportSubMenuItem.onSelected?.(),
...
}
: {// normal: opens the Export submenuicon: expensifyIcons.Export,rightIcon: expensifyIcons.ArrowRight,text: translate('common.export'),
subMenuItems,};
So when Export is the only "More" option and there's only one export option, the user is taken straight into that option, losing the "you're exporting" context — exactly the confusing two-menus-skipped behavior in the issue. This collapse only exists on the Search/Spend path; the report-header and selected-transactions paths (useExportActions.ts:268, useSelectedTransactionsActions.ts:449-456) already keep subMenuItems, so they behave correctly today.
What changes do you think we should make in order to solve the problem?
Remove the single-option collapse in useSearchBulkActions.ts so the Export entry always uses the submenu form (the else branch above). Concretely, delete singleExportSubMenuItem and always build exportButtonOption with text: translate('common.export'), rightIcon: expensifyIcons.ArrowRight, and subMenuItems.
With subMenuItems present, PopoverMenu.selectItem navigates one level deeper into the Export submenu (showing the single option with a back button) instead of executing it — which is the desired "open the flow one level deeper instead of two" behavior. No change is needed in the report-header/transaction paths since they never collapsed.
What alternative solutions did you explore? (Optional)
Keeping the collapse but only when it also collapses the top-level "More" menu (i.e. only skip a level when Export truly is the only action) — rejected because the issue explicitly wants the intermediate Export menu shown even in the single-option case, and it adds a special case rather than making the three export paths consistent.
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/98779) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
🤖 Draft PR created: #99217
Please mark it as "Ready for review" when it is ready for review.
What changed: Removed the single-option collapse in useSearchBulkActions.ts so the Search/Spend "More" menu's Export entry always opens the Export submenu — showing the single available option one level deeper instead of navigating straight into it. The report-header and selected-transactions export paths already behaved this way and are untouched.
Tests: Added a regression test in useSearchBulkActionsExportTest.ts that fails on the old collapsing code and passes with the fix. Ran locally: lint-changed ✅, typecheck-tsgo ✅, react-compiler compliance (no regression) ✅, spell-changed ✅, and the export/bulk-actions Jest suites ✅ (27 + button tests passing).
One note for QA: this only affects the Search/Spend flow. Reproducing the single-option case requires a selection whose export list resolves to exactly one option (e.g. a grouped/full-group selection that offers only "Current view") — with the fix, tapping Export should now show that option inside the Export submenu rather than jumping straight into it.
[Contributor] The offending PR and associated issue have been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.
It's a new feature
[Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.
Link to discussion:
[Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.
Precondition:
Test:
Open App
Sign in to an account that has expenses/reports.
Go to a Search page (e.g. Reports or Expenses) and select one or more rows so the bulk-action toolbar appears.
With other bulk actions present in the More (⋮) dropdown, click Export and verify it opens the Export submenu with a generic "Export" label, a back button, and the export options listed one level deeper — it does NOT jump straight into a single option.
Verify the back button returns you to the More menu.
Use Select all matching so Export is the only bulk action, open the More (⋮) dropdown, and verify it opens directly onto the export options, headed by a plain "Export" title with no back arrow and no "Export" row to click through.
Reviewer checklist 5 of 5 with a video. Author checklist 0 of 5 boxes checked
Job price $250. No price in the title.
Contributor: nothing due. Melvin wrote the PR.
Contributor+: 100%. The reviewer checklist is complete and carries a video on all five platforms.
No regression cut. No blocker linked.
No increase. Below the 25 file and 1000 line thresholds.
Reported, not deducted: Melvin's own author checklist has 0 of 5 boxes checked and no evidence. The author here is Melvin, so no payment turns on it, but the same gap on a human-authored PR would be worth seeing.
Claude posting on behalf of Matt. PAYRUBRICTEST v2
@ZhenjaHorbach please use the exact template here when posting the C+ Checklist (partially cuz I have automation build and need the exact format). The button to auto-post the checklist should be fixed soon. Thx
Activity
melvin-bot commentedon Aug 21, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @ZhenjaHorbach (
External)melvin-bot commentedon Aug 21, 2026
Unable to auto-create job on Upwork. The BZ team member should create it manually for this issue.
flaviadefaria commentedon Aug 21, 2026
@ZhenjaHorbach, I think Melvin might be able to implement this. What do you think?
ZhenjaHorbach commentedon Aug 21, 2026
Sounds good!
ZhenjaHorbach commentedon Aug 21, 2026
@MelvinBot
Can you prepare a proposal?
MelvinBot commentedon Aug 21, 2026
Proposal
What is the root cause of that problem?
The Search/Spend "More" menu deliberately collapses the Export flow whenever exactly one export option is available. In
useSearchBulkActions.ts:2085-2108, whengetExportOptions()returns a single item, the code builds the Export entry as a flat button that runs that option'sonSelecteddirectly (nosubMenuItems) instead of the normal entry that opens the Export submenu:Root-cause code
So when Export is the only "More" option and there's only one export option, the user is taken straight into that option, losing the "you're exporting" context — exactly the confusing two-menus-skipped behavior in the issue. This collapse only exists on the Search/Spend path; the report-header and selected-transactions paths (
useExportActions.ts:268,useSelectedTransactionsActions.ts:449-456) already keepsubMenuItems, so they behave correctly today.What changes do you think we should make in order to solve the problem?
Remove the single-option collapse in
useSearchBulkActions.tsso the Export entry always uses the submenu form (theelsebranch above). Concretely, deletesingleExportSubMenuItemand always buildexportButtonOptionwithtext: translate('common.export'),rightIcon: expensifyIcons.ArrowRight, andsubMenuItems.With
subMenuItemspresent,PopoverMenu.selectItemnavigates one level deeper into the Export submenu (showing the single option with a back button) instead of executing it — which is the desired "open the flow one level deeper instead of two" behavior. No change is needed in the report-header/transaction paths since they never collapsed.What alternative solutions did you explore? (Optional)
Keeping the collapse but only when it also collapses the top-level "More" menu (i.e. only skip a level when Export truly is the only action) — rejected because the issue explicitly wants the intermediate Export menu shown even in the single-option case, and it adds a special case rather than making the three export paths consistent.
Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/98779)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
view run
ZhenjaHorbach commentedon Aug 21, 2026
@MelvinBot
Implement your proposal
MelvinBot commentedon Aug 21, 2026
🤖 Draft PR created: #99217
Please mark it as "Ready for review" when it is ready for review.
What changed: Removed the single-option collapse in
useSearchBulkActions.tsso the Search/Spend "More" menu's Export entry always opens the Export submenu — showing the single available option one level deeper instead of navigating straight into it. The report-header and selected-transactions export paths already behaved this way and are untouched.Tests: Added a regression test in
useSearchBulkActionsExportTest.tsthat fails on the old collapsing code and passes with the fix. Ran locally: lint-changed ✅, typecheck-tsgo ✅, react-compiler compliance (no regression) ✅, spell-changed ✅, and the export/bulk-actions Jest suites ✅ (27 + button tests passing).One note for QA: this only affects the Search/Spend flow. Reproducing the single-option case requires a selection whose export list resolves to exactly one option (e.g. a grouped/full-group selection that offers only "Current view") — with the fix, tapping Export should now show that option inside the Export submenu rather than jumping straight into it.
view run
melvin-bot commentedon Aug 24, 2026
@ZhenjaHorbach Whoops! This issue is 2 days overdue. Let's get this updated quick!
12 remaining items
melvin-bot commentedon Sep 8, 2026
@ZhenjaHorbach Huh... This is 4 days overdue. Who can take care of this?
melvin-bot commentedon Sep 9, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)melvin-bot commentedon Sep 9, 2026
Payment Summary
Resolving PRs:
Always open the Export submenu on Search, even with a single export option #99217
Reviewer: @ZhenjaHorbach owed $250 via NewDot
BugZero Checklist (@mallenexpensify)
ZhenjaHorbach commentedon Sep 10, 2026
Contributor+ Checklist:
It's a new feature
[Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.
Link to discussion:
[Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.
Precondition:
Test:
Do we agree 👍 or 👎
melvin-bot commentedon Sep 14, 2026
@mallenexpensify Huh... This is 4 days overdue. Who can take care of this?
mallenexpensify commentedon Sep 14, 2026
Claude posting on behalf of Matt:
$250 to @ZhenjaHorbach (Contributor+).
To pay, copy this block and paste it into the comment box:
How the amount is reached
Reported, not deducted: Melvin's own author checklist has 0 of 5 boxes checked and no evidence. The author here is Melvin, so no payment turns on it, but the same gap on a human-authored PR would be worth seeing.
Claude posting on behalf of Matt.
PAYRUBRICTEST v2mallenexpensify commentedon Sep 15, 2026
Payment Summary
Contributor+: @ZhenjaHorbach due $250 via NewDot
@ZhenjaHorbach please use the exact template here when posting the C+ Checklist (partially cuz I have automation build and need the exact format). The button to auto-post the checklist should be fixed soon. Thx
garrettmknight commentedon Oct 7, 2026
$250 approved for @ZhenjaHorbach