Skip to content

Add share option to saved searches overflow menu#88768

Merged
aldo-expensify merged 14 commits into
Expensify:mainfrom
aswin-s:feat/add-share-option-to-saved-searches
May 12, 2026
Merged

Add share option to saved searches overflow menu#88768
aldo-expensify merged 14 commits into
Expensify:mainfrom
aswin-s:feat/add-share-option-to-saved-searches

Conversation

@aswin-s
Copy link
Copy Markdown
Contributor

@aswin-s aswin-s commented Apr 25, 2026

Explanation of Change

Adds a Share option to the saved searches overflow menu (both in the wide layout SavedSearchList and narrow layout SearchTypeMenuNarrow). Tapping Share copies the search URL to the clipboard and briefly shows a "URL copied" confirmation with a checkmark icon for 1.8 seconds. The menu stays open during the feedback so the user can see the confirmation.

Fixed Issues

$ #87627
PROPOSAL: #87627 (comment)

Tests

  1. Open the app and save a search
  2. Long-press (narrow) or open the three-dot menu (wide) on a saved search
  3. Tap Share
  4. Verify the menu stays open and the item changes to show a checkmark and "URL copied"
  5. After ~1.8 seconds, verify the item reverts to the share icon and label
  6. Paste from clipboard and verify the URL navigates to the correct saved search
  • Verify that no errors appear in the JS console

Offline tests

The share action only copies a URL to the clipboard — no network requests are made. Behavior is identical offline.

QA Steps

Same as tests above.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
88768-android-native.mp4
Android: mWeb Chrome
88768-android-web.mp4
iOS: Native
8878-ios-native.mp4
iOS: mWeb Safari
8878-ios-web.mp4
MacOS: Chrome / Safari
88768-MacOS.mp4

@melvin-bot
Copy link
Copy Markdown

melvin-bot Bot commented Apr 25, 2026

Hey, I noticed you changed src/languages/en.ts in a PR from a fork. For security reasons, translations are not generated automatically for PRs from forks.

If you want to automatically generate translations for other locales, an Expensify employee will have to:

  1. Look at the code and make sure there are no malicious changes.
  2. Run the Generate static translations GitHub workflow. If you have write access and the K2 extension, you can simply click: [this button]

Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running:

npx ts-node ./scripts/generateTranslations.ts --help

Typically, you'd want to translate only what you changed by running npx ts-node ./scripts/generateTranslations.ts --compare-ref main

@aswin-s aswin-s force-pushed the feat/add-share-option-to-saved-searches branch from ee0bd6c to dda5591 Compare April 25, 2026 03:41
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 25, 2026

Codecov Report

❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.

Files with missing lines Coverage Δ
src/hooks/useShareSavedSearch.ts 100.00% <100.00%> (ø)
src/components/ThreeDotsMenu/index.tsx 85.93% <0.00%> (ø)
src/libs/SearchUIUtils.ts 63.72% <0.00%> (-0.12%) ⬇️
src/pages/Search/SearchTypeMenuNarrow.tsx 74.68% <33.33%> (-2.65%) ⬇️
src/pages/Search/SavedSearchList.tsx 0.00% <0.00%> (ø)
src/pages/Search/SavedSearchItemThreeDotMenu.tsx 0.00% <0.00%> (ø)
... and 7 files with indirect coverage changes

@aswin-s aswin-s marked this pull request as ready for review April 27, 2026 09:19
@aswin-s aswin-s requested review from a team as code owners April 27, 2026 09:19
@melvin-bot melvin-bot Bot requested review from JmillsExpensify and jayeshmangwani and removed request for a team and jayeshmangwani April 27, 2026 09:19
@melvin-bot
Copy link
Copy Markdown

melvin-bot Bot commented Apr 27, 2026

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

@aswin-s aswin-s force-pushed the feat/add-share-option-to-saved-searches branch 2 times, most recently from 50d0704 to 0429426 Compare April 28, 2026 23:35
@jayeshmangwani
Copy link
Copy Markdown
Contributor

I will review this today. I was OOO, sorry for the delay.

@jayeshmangwani
Copy link
Copy Markdown
Contributor

@aswin-s I initially faced a crash when opening the Spend tab. I suspect the change from import React from 'react'; to import type React from 'react'; in src/pages/Search/SavedSearchList.tsx may be causing it.
Screenshot 2026-05-03 at 10 34 17 AM

@jayeshmangwani
Copy link
Copy Markdown
Contributor

The URL copied text doesn’t look good, I think it has the same color as the Share text. Tagging @shawnborton to get their consensus.
Screenshot 2026-05-03 at 10 35 25 AM


Share text

Screenshot 2026-05-03 at 10 35 23 AM

@aswin-s
Copy link
Copy Markdown
Contributor Author

aswin-s commented May 3, 2026

@jayeshmangwani Good catch! The confirmation state now matches the Context Menu → Copy Link pattern for consistency.

Context Menu:

image

Saved Search:

image

@shawnborton Quick question: should we add an exclamation mark after "Copied" to match the context menu's "Copied!" text?

@shawnborton
Copy link
Copy Markdown
Contributor

Yeah, that makes sense to me. cc @Expensify/marketing for viz on that but let's do it!

@shawnborton
Copy link
Copy Markdown
Contributor

And yes, I agree we want the styles/colors to exactly match what we have for the Copy text action.

@jayeshmangwani
Copy link
Copy Markdown
Contributor

@aswin-s, checkbox icon should be green.

Also, I think that once the Share button is pressed and ‘URL copied’ appears, the modal should close automatically after ~2 seconds.

@aswin-s aswin-s force-pushed the feat/add-share-option-to-saved-searches branch from 970903e to 7efb7e8 Compare May 4, 2026 08:30
@aswin-s
Copy link
Copy Markdown
Contributor Author

aswin-s commented May 4, 2026

@jayeshmangwani I've updated the implementation to replicate the ContextMenu behaviour for consistency
with the existing pattern. That said, worth calling out two things:

  1. The menu closes ~800ms after clicking copy link — this matches the shouldDelay timing used in
    hideContextMenu for the ContextMenu's copy link action.
  2. The checkmark appears in grey/disabled color — this is actually consistent with the existing
    ContextMenu pattern, where the ContextMenuItem renders the icon in the default color during the success
    state (because interactive={false} short-circuits getButtonState to DEFAULT before reaching COMPLETE).

So the green checkmark shown in the issue video is not how the existing ContextMenu pattern works.
Should we keep it consistent with the current ContextMenu behaviour (grey), or intentionally deviate
and make it green as shown in the issue?

@aswin-s
Copy link
Copy Markdown
Contributor Author

aswin-s commented May 4, 2026

Also looks like typecheck is failing on main branch. It is unrelated to our changes.

@jayeshmangwani
Copy link
Copy Markdown
Contributor

@aswin-s Can we also close the modal on mobile devices? Also, can we merge main to check if the failing test is resolved?

mobile-bug.mov

@jayeshmangwani
Copy link
Copy Markdown
Contributor

Can we update the cursor to show the normal pointer instead of "not-allowed", similar to how it works for message copy on the report page?
Screenshot 2026-05-05 at 11 01 16 AM

@aswin-s aswin-s force-pushed the feat/add-share-option-to-saved-searches branch from bc8af4d to 94750ff Compare May 5, 2026 07:44
@aswin-s
Copy link
Copy Markdown
Contributor Author

aswin-s commented May 5, 2026

@jayeshmangwani Fixed the native experience as well and updated the videos for all devices in OP. Rebased with main but the fix for typescript lint has not landed yet.

@jayeshmangwani
Copy link
Copy Markdown
Contributor

@aswin-s Types are failing only on our PR because we’re passing personalPolicyID={undefined} in tests/ui/PureReportActionItemTest.tsx, but the personalPolicyID prop was removed in this PR #89160.

aswin-s added 8 commits May 7, 2026 17:08
- Remove useCallback from useShareSavedSearch hook (React Compiler handles memoization)
- Move shouldCloseModalOnSelect check into PopoverMenu to avoid duplication
- Remove redundant guards from ThreeDotsMenu and SearchTypeMenuNarrow callers
… state

Matches context menu copy pattern: grey checkmark icon with black label text.
@aswin-s aswin-s force-pushed the feat/add-share-option-to-saved-searches branch from 00d5a20 to 9eb891f Compare May 7, 2026 11:38
aswin-s added 2 commits May 7, 2026 17:25
…and guard ThreeDotsMenu hide

Restores the onItemSelected call in PopoverMenu's shouldCloseModalOnSelect===false
branch to preserve generic behaviour for all callers (e.g. ButtonWithDropdownMenu).
Guards ThreeDotsMenu.hidePopoverMenu against shouldCloseModalOnSelect===false so the
menu stays open for items like Copy Link, matching the existing shouldKeepModalOpen pattern.
…election

Guard onItemSelected in SearchTypeMenuNarrow to not close the popover when
shouldCloseModalOnSelect is false, matching the same pattern used in
ButtonWithDropdownMenu and ThreeDotsMenu.
@aswin-s
Copy link
Copy Markdown
Contributor Author

aswin-s commented May 7, 2026

@jayeshmangwani Fixed everything and rebased with main.

@jayeshmangwani
Copy link
Copy Markdown
Contributor

@aswin-s , everything looks good to me. Could you please add the Slack link for the translation confirmation?

@aswin-s
Copy link
Copy Markdown
Contributor Author

aswin-s commented May 9, 2026

@jayeshmangwani Added translation request here. Yet to get a confirmation.
https://expensify.slack.com/archives/C01GTK53T8Q/p1778179785608289

@aswin-s
Copy link
Copy Markdown
Contributor Author

aswin-s commented May 11, 2026

@jayeshmangwani Re-requested the translation and it is approved.

https://expensify.slack.com/archives/C01GTK53T8Q/p1778527194871009

@jayeshmangwani
Copy link
Copy Markdown
Contributor

Thanks for confirming the translation.

Copy link
Copy Markdown
Contributor

@jayeshmangwani jayeshmangwani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

@melvin-bot melvin-bot Bot requested a review from aldo-expensify May 12, 2026 12:14
@aldo-expensify aldo-expensify merged commit 274006b into Expensify:main May 12, 2026
39 checks passed
@OSBotify
Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@github-actions
Copy link
Copy Markdown
Contributor

🚧 @aldo-expensify has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify
Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/aldo-expensify in version: 9.3.73-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 failure ❌
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

@MelvinBot
Copy link
Copy Markdown
Contributor

Yes, the help site needs a minor update. The article Using-Reports-in-New-Expensify.md describes saved search management actions (rename, delete) but doesn't mention the new Share option.

I've created a draft PR with the update: #90427

Changes made:

  • Updated the saved search management sentence to include "share" alongside rename and delete, and added a note that Share copies the search URL to the clipboard
  • Added "share saved search" to article keywords for discoverability

@OSBotify
Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/aldo-expensify in version: 9.3.73-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

@OSBotify
Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/Beamanator in version: 9.3.73-4 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants