Always open the Export submenu on Search, even with a single export option - #99217
Conversation
Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
…rrentView) Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
Android test results — PR #99217 ✅ PASSI ran the testing steps on Android: Native (standalone NewDot) and confirmed the core change: tapping Export in the selection More menu now opens the intermediate Export submenu (header + back button) instead of jumping straight into a final export action. Steps run
Result: ✅ Export always routes through the submenu — it never skips straight to a final action. Caveat on the single-option scenarioThis personal/unconnected test account exposed 3 export options ( No JS/console errors were observed during the flow. |
|
Fixed the failing Root cause: This PR's source change made the Export entry in
Both grabbed the export handler via Fix: point those two lookups at the actual sole submenu item, Change
Test-only change, faithful to the assertions (exclusion tracking for the expense select-all case; no exclusions for the expense-report case). I verified the fix by tracing The other failing check, |
|
The test failure is resolved — my earlier fix to The only remaining red check is Nothing further to fix on my end. |
Web test results — PR #99217 ✅ PASSI ran the testing steps on Web (dev NewDot) and confirmed the core change: clicking Export in the selection More menu now opens the intermediate Export submenu (labeled "Export" with a back button) instead of jumping straight into a final export action. Steps run
Result: ✅ Export always routes through the submenu — it never skips straight to a final action. ScreenshotsSelection "More" menu — Export shown with a submenu chevron: Export submenu — "Go back / Export" header with the option list: Caveat on the single-option scenarioThis test account exposed 3 export options ( No JS/console errors were observed during the flow. |
|
@MelvinBot |
|
🤖 I tried to run the web test steps for this PR, but I couldn't complete the live verification: the test account had no expenses or reports, so the bulk-action toolbar (and therefore the "More" → Export entry) was never reachable. Both Search → Expenses and Search → Reports render empty states with no rows to select. What I confirmed at the code level (not a substitute for the live UI check): on this branch, To exercise this in the browser, an account with selectable expenses/reports (ideally a grouped/report view that offers a single export option) is needed. EvidenceSearch > Reports tab showing 'No reports yet' empty state, confirming no data available to select
|
|
@MelvinBot |
|
@MelvinBot |
|
@ZhenjaHorbach Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Reviewer Checklist
Screenshots/VideosAndroid: HybridApp2026-09-01.13.24.05.movAndroid: mWeb Chrome2026-09-01.13.29.15.moviOS: HybridApp2026-09-01.13.24.05.moviOS: mWeb Safari2026-09-01.13.29.15.movMacOS: Chrome / Safari2026-09-01.12.57.22.mov |
|
@MelvinBot |
|
🤖 Updated the PR description and filled in the testing sections + author checklist. What changed:
Left unchecked — need a human:
|
|
@flaviadefaria Instead of showing only Export, for example 2026-08-25.12.58.27.movWe want to show the Export submenu 2026-08-25.12.59.08.movRight? |
garrettmknight
left a comment
There was a problem hiding this comment.
Looks good from a product perspective
Yeah |
|
@MelvinBot |
…tionSubmenu Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
|
Branch updated — merged the latest The PR's own diff against Re-verified locally after the merge: CI on The single failure is Live web check: not run. For the third run in a row the |
The test derived its expected ETA from getNextNthOfMonth, which always skips to next month, while buildOptimisticNextStep treats an offset landing on today as due today. The two only disagree when the suite runs on the 2nd, so the test failed for every PR on that day. Pin the system time to a day that is not the 2nd to make it deterministic. Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
d10d8ed
|
@MelvinBot |
|
All CI checks now pass. The only remaining red mark is What was failing: Root cause: the test and the production code disagree about whether "the next 2nd" includes today.
They only diverge when today is the nth, which is why this surfaces one day a month. Fix (
Verification
|
|
@MelvinBot |
This reverts commit d10d8ed.
…tionSubmenu Co-authored-by: Yauheni Horbach <ZhenjaHorbach@users.noreply.github.com>
|
Done — both, pushed as Removed the unrelated test fix. A later run of mine had committed Fixed the conflicts by merging CI is green on Live web check: not run. The |
|
All CI checks now pass on The one remaining red check is Both earlier failures are resolved:
How I verified
|
|
@chuckdries |
|
Nothing to do — this PR was already merged into What happened before the mergeThe branch was already brought up to date with That second merge pulled in If you meant a different PR, point me at its number and I'll merge |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/chuckdries in version: 9.4.69-0 🚀
|
|
Yes — one help article needed updating. Draft PR: #100233. Export Expenses and Reports told members to select Current view straight from the selection dropdown when exporting grouped expenses. That was correct before this PR, because a group selection offers only one export option (Current view), so the Export row collapsed and surfaced it at the top level. Now Export no longer collapses, so when other bulk actions are present the option sits one level deeper — the docs skipped that click. Three lines changed in
Why no other article changed, and two pre-existing issues I found
I checked the labels against the live UI on a dev build of Two label mismatches predate this PR, so I left them out of the docs PR — tell me if you want them fixed:
The behavior this PR relies on is pinned by @ZhenjaHorbach, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR |
|
🚧 chuckdries has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to production by https://github.com/francoisl in version: 9.4.69-1 🚀
Bundle Size Analysis (Sentry): |




Explanation of Change
On the Spend page and other Search pages, the "More" (⋮) menu's Export entry collapsed into a direct action whenever only one export option was available: instead of opening the Export submenu, it navigated straight into that single option. This dropped the user two levels deep at once and lost the context that they were entering an export flow.
This PR makes two changes:
src/hooks/useSearchBulkActions.ts, the single-option collapse is gone, so Export always opens the Export submenu — keeping its generic "Export" label and back button — and shows the single available option one level deeper instead of two.The header is produced by
bulkActionsMenuHeaderText, whichSearchBulkActionsButtonpasses toButtonWithDropdownMenu's existingmenuHeaderTextprop.PopoverMenualready renders that header only at the top level, so no shared component needed changing.The report-header and selected-transactions export paths already behaved this way and are unchanged.
Fixed Issues
$ #98779
PROPOSAL: #98779 (comment)
Tests
Offline tests
Same as Tests — this change only affects how the client-side dropdown is structured, so behavior is identical online and offline. Verify the menu levels behave the same while offline.
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari