Migrate ComposedButton to ButtonWithDropdownMenu#93789
Conversation
…-fork into Guccio163/button/ButtonWithDropdownMenu
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
@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] |
|
Oh |
…-fork into Guccio163/button/ButtonWithDropdownMenu
…-fork into Guccio163/button/ButtonWithDropdownMenu
…-fork into Guccio163/button/ButtonWithDropdownMenu
|
No product review needed |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridApp2026-07-02.14.18.56.mov2026-07-02.14.19.12.mov2026-07-02.14.19.39.mov2026-07-02.14.21.54.mov2026-07-02.14.22.20.mov2026-07-02.14.23.01.mov2026-07-02.14.24.38.mov2026-07-02.14.27.28.mov2026-07-02.14.28.34.mov2026-07-02.14.29.23.moviOS: mWeb Safari2026-07-02.13.27.39.mov2026-07-02.13.30.53.mov2026-07-02.13.39.36.mov2026-07-02.13.40.23.mov2026-07-02.13.41.47.mov2026-07-02.13.44.17.mov2026-07-02.13.44.58.mov2026-07-02.14.04.06.mov2026-07-02.14.04.58.movMacOS: Chrome / Safari2026-07-02.12.06.56.mov2026-07-02.12.07.25.mov2026-07-02.12.08.10.mov2026-07-02.12.18.39.mov2026-07-02.12.20.46.mov2026-07-02.12.21.38.mov2026-07-02.12.22.19.mov2026-07-02.12.23.21.mov2026-07-02.12.27.45.mov |
…-fork into Guccio163/button/ButtonWithDropdownMenu
…-fork into Guccio163/button/ButtonWithDropdownMenu
…-fork into Guccio163/button/ButtonWithDropdownMenu
|
I also restored the ButtonProps barrel export, just a sidenote; @ZhenjaHorbach I think all checks are passing, so we can also check this one ✅ |
|
From my side everything is good! |
|
@codex |
|
@MelvinBot |
|
🤖 PR Review — mostly a clean mechanical migration, but there's one behavior change worth confirming before merge.
|
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
As I remeber we decided to remove extraSmall a bit later |
|
Exactly, moreover |
| type DoubleLineButtonTextProps = { | ||
| primaryText: string; | ||
| primaryTextStyle?: StyleProp<TextStyle>; | ||
| secondLineText: string; | ||
| }; |
| stayNormalOnDisable={shouldStayNormalOnDisable} | ||
| isLoading={isLoading} | ||
| shouldRemoveRightBorderRadius | ||
| removeBorderRadius="right" |
There was a problem hiding this comment.
Is there no const for this?
| <Button | ||
| success={success} | ||
| pressOnEnter={pressOnEnter} | ||
| variant={success ? 'success' : undefined} |
There was a problem hiding this comment.
no const for the success variant?
|
🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
Right, I'll address the comments in the follow-up; Do you think we should make consts for these two button props? They are already type-guarded for only the allowed options, but if you prefer I can also change this into consts, just LMKWYT @mountiny |
|
I feel like the consts make it a bit cleaner if the value is reused somewhere |
|
It sure does; I wasn't sure if we want to add more consts just for this one component, but surely those ~300 calls should be enough to introduce them 😆 |
|
🚀 Deployed to staging by https://github.com/mountiny in version: 9.4.28-0 🚀
|
|
🤖 Help site review — no changes required. I reviewed this PR's changes against Expensify's help site content under Why: This is a purely internal component refactor with no user-facing surface that the help site describes:
Help articles document product features and flows (how to pay/approve reports, workspace settings, etc.), none of which change here. The one behavioral nuance I flagged in my code review (Search-list Pay button losing its extra-small size on narrow screens) is a visual sizing detail that isn't covered by any help article, so it needs no docs update regardless of how that's resolved. If a reviewer believes a specific article is affected, reply with the article path and I'll draft the update. |
|
Hello @ZhenjaHorbach @Guccio163
|
|
Sorry @lanitochka17, those test steps were outdated, I just updated them so should be fine ✔️ |
|
🚀 Deployed to production by https://github.com/mountiny in version: 9.4.28-2 🚀
Bundle Size Analysis (Sentry): |

Explanation of Change
This PR is a part of ButtonComposed migration, implementing the new composed Button from ./ButtonComposed instead of ./Button in the ButtonWithDropdownMenu.
This PR removes ButtonDoubleLineText component, since its only potential usage was inside the ButtonWithDropdownMenu and we can simply use it inline. It also removes the ButtonWithIcons - Button wrapper which is no longer needed, since all of the icon+text coupling logic is gone/implemented inline in designated places.
Fixed Issues
$ #83762
PROPOSAL:
Tests
ButtonWithDropdownMenucan include icons, text and second-line text. Below are test steps for 3 UIvariants of
ButtonWithDropdownMenu, verify that all of them are correct. Correctness means the buttonis identical to the current one (main/staging/prod); subtle changes like the gap between the text and
icon are also intentional.
All three variants are reached via the report-header pay button (
SettlementButton), which is the onlyplace in the app that renders every form (single, split-with-arrow, and double-line).
Variant 1: "Mark as paid" (single button — text only, NO icon, NO dropdown arrow)
What we're testing: BWDM as a single button — just Button.Text ("Mark as paid"). No leading icon
(SettlementButton doesn't pass an icon), no dropdown arrow, no second line.
Steps (needs a second test account, "User B"):
USD/AUD/CAD/GBP/EUR — e.g. PLN, amount e.g. 50. (Set the currency on the amount screen before
creating.) This makes User A the payer on the resulting IOU.
Variant 2: "Pay $XX" (split button — dropdown arrow visible, single-line label)
What we're testing: BWDM as a split button — text + dropdown-arrow icon, no subtitle.
Steps:
auto-created). Keep the workspace currency as USD.
CLOSE / skip it — do NOT connect an account.
→ Create expense.
"Pay elsewhere".
Variant 3: "Pay $XX" + second-line text (split button WITH subtitle / double-line)
What we're testing: BWDM with double-line text — line 1 amount, line 2 payment-method subtitle. This is the only path in the app that produces
secondLineText(SettlementButton).Steps:
Note: the old "enable Wallet → Wallet subtitle" path does NOT apply to expense reports (wallet payment
is only offered on P2P/invoice reports), so the expense-report subtitle comes from the connected VBBA.
Pragmatic alternative (if KYC/bank setup is too slow): import the prepared Onyx state
Offline tests
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, 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)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.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
Screen.Recording.2026-06-18.at.17.45.27.mov
Screen.Recording.2026-06-18.at.18.00.30.mov
Screen.Recording.2026-06-18.at.18.00.59.mov
Android: mWeb Chrome
Screen.Recording.2026-06-18.at.17.48.56.mov
Screen.Recording.2026-06-18.at.17.57.48.mov
Screen.Recording.2026-06-18.at.17.59.10.mov
iOS: Native
Screen.Recording.2026-06-18.at.18.07.00.mov
Screen.Recording.2026-06-18.at.18.07.34.mov
Screen.Recording.2026-06-18.at.17.15.59.mov
iOS: mWeb Safari
Screen.Recording.2026-06-18.at.18.11.51.mov
Screen.Recording.2026-06-18.at.18.12.14.mov
Screen.Recording.2026-06-18.at.17.22.25.mov
MacOS: Chrome / Safari
Screen.Recording.2026-06-18.at.19.09.36.mov
Screen.Recording.2026-06-18.at.19.10.39.mov
Screen.Recording.2026-06-18.at.13.20.54.mov