Migrate Button to ButtonComposed (batch 3) - #96627
Conversation
…-fork into button-migration-pr3-3rd
…-fork into button-migration-pr3-3rd
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
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] |
|
PR doesn’t need product input as a refactor PR. Unassigning and unsubscribing myself. |
|
@ZhenjaHorbach bump on this one, looks like this slipped through the cracks |
Reviewer Checklist
Screenshots/VideosAndroid: HybridApp2026-07-27.14.33.30.mov2026-07-27.14.34.50.mov2026-07-27.14.35.52.mov2026-07-27.14.36.20.mov2026-07-27.14.36.51.mov2026-07-27.14.37.16.movAndroid: mWeb Chrome2026-07-27.14.06.21.mov2026-07-27.14.07.09.mov2026-07-27.14.08.39.mov2026-07-27.14.09.18.mov2026-07-27.14.09.40.mov2026-07-27.14.15.22.moviOS: HybridApp2026-07-27.14.33.30.mov2026-07-27.14.34.50.mov2026-07-27.14.35.52.mov2026-07-27.14.36.20.mov2026-07-27.14.36.51.mov2026-07-27.14.37.16.moviOS: mWeb Safari2026-07-27.14.06.21.mov2026-07-27.14.07.09.mov2026-07-27.14.08.39.mov2026-07-27.14.09.18.mov2026-07-27.14.09.40.mov2026-07-27.14.15.22.movMacOS: Chrome / Safari2026-07-27.13.59.05.mov2026-07-27.13.59.34.mov2026-07-27.14.00.52.mov2026-07-27.14.01.36.mov2026-07-27.14.02.15.mov2026-07-27.14.03.08.mov |
|
Changes look good! |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚧 mountiny 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 staging by https://github.com/mountiny in version: 9.4.45-0 🚀
|
Help site review: no changes requiredI reviewed the changes in this PR and no updates to Expensify's help site files ( Why: This PR is a purely internal component migration — every changed file just swaps
Help site articles document user-facing product features and workflows, none of which are affected by this refactor. There is nothing to document. If you believe a specific user-facing behavior did change and should be reflected in the docs, let me know which one and I'll take another look. |
|
🚀 Deployed to production by https://github.com/marcaaron in version: 9.4.45-14 🚀
Bundle Size Analysis (Sentry): |
This is a duplicate of closed PR: #96270
Explanation of Change
This is batch 3 (PR3 of 9) of an ongoing effort to migrate every direct
<Button>usage (import Button from '@components/Button') over to the new composedButtonComposed, so the oldButtoncomponent can eventually be deprecated. This batch covers 33 files / ~41 button instances (34 files were listed in the migration issue for this batch. One file,src/pages/workspace/members/WorkspaceOwnerChangeErrorPage.tsx, doesn't exist under that name — the real file issrc/pages/workspace/members/members/DynamicWorkspaceOwnerChangeErrorPage.tsx)Fixed Issues
$ #95171
PROPOSAL: #83762 (comment)
Tests
For every migrated button, verify that behaviour is unchanged from before the migration:
success= green,danger= red, default = grey.isLoading).<Button.KeyboardShortcut>).Moreover, I divided migrated buttons into several categories, based on their custom styling or behavior which is applied in the application:
isDisabled={isOffline})isLoading)onPressstill opens a read-only modal instead of doing nothing (distinct from the true offline-disabled case above)For each of these categories, detailed test steps are described in sections below:
Plain button
Preconditions
Test steps
Expected behavior
Button on the bottom should render correctly and display Save text. It should match the
rendering from a production build.
Button with a loading spinner
While loading spinner state is not easily achievable, there are several ways to reach this behavior on web:
Option A: Click right mouse button on page and go to Console. There, paste
Onyx.merge('settingsStatusSetForm', {isLoading: true})and press Enter.Option B: Open file StatusPage.tsx in the application's codebase and replace
isLoading={isFormLoading}withisLoading={true}.Expected behavior
The button's text is replaced by a spinner and the button can't be clicked.
Button whose layout adapts to screen size, and looks greyed out for some members
Preconditions
(a promo banner with this button only shows up in that case).
Test steps
narrow and wide (or rotate the device/simulator).
Expected behavior
As Admin: the button's layout changes between a full-width row and a smaller inline button as the
window gets narrower or wider, with no cut-off text at either size.
Button that looks greyed out for one specific workspace role
Preconditions
Auditor. (A regular "Member" role won't even be able to open this page at all — you'll
need to be on Auditor specifically to see the greyed-out button described below.)
Test steps
again.
Expected behavior
As Auditor: the Connect button looks greyed out but is still clickable — clicking it pops up
a message saying you can view this but can't make changes, instead of connecting anything. As
Admin: the same button looks normal (not greyed out), and clicking it actually starts connecting.
Button that opens a confirmation popup before doing anything
Preconditions
None — any account works.
Test steps
Expected behavior
Clicking Lock account should never lock the account right away — a confirmation popup should
appear first, asking you to confirm. Only clicking the confirm button inside that popup should
actually lock the account (and briefly show a loading state while it does). The button and popup
should look and behave the same as before this change.
Button that changes label/appearance depending on account state
Preconditions
Control plan) — just being an Admin of one isn't enough; if you're not the owner, the whole
Subscription page will appear blank.
Test steps
Expected behavior
clickable button there.
Clicking it either applies the change right away, or takes you to a separate upgrade/downgrade
page, depending on your account setup — either way, no crash or blank screen.
All of the above should look and behave the same as they did before this change.
Offline tests
Similarly to the regular tests, offline testing steps take focus on one of the representatives for this category:
Test steps
step.
screen.
afterward.
Expected behavior
Whenever you're offline — whether you went offline while already on the page, or loaded the page
while already offline — the Add copilot button should look greyed out and not respond to
clicks. As soon as you're back online, it should immediately look normal and clickable again,
with no delay or stuck state.
QA Steps
Same as tests/offline tests
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)Designlabel and/or tagged@Expensify/designso the design team can review the changes.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
add_delegate_offline_behavior_android.mp4
buttons_admin_action_hr_android.mp4
company_cards_width_behavior_android.mp4
dangerous_buttons_lock_account_android.mp4
disabled_buttons_alt_action_hr_android.mp4
multiple_states_buttons_down_upgrade_android.mp4
status_activityindicator_behavior_android.mp4
tax_value_button_plain_android.mp4
Android: mWeb Chrome
add_delegate_offline_behavior_android_web.mp4
company_cards_width_behavior_android_web.mp4
dangerous_buttons_lock_account_android_web.mp4
disabled_buttons_alt_action_hr_android_web.mp4
multiple_states_buttons_down_upgrade_android_web.mp4
status_activityindicator_behavior_android_web.mp4
tax_value_button_plain_android_web.mp4
iOS: Native
add_delegate_offline_behavior_ios.mp4
buttons_admin_action_hr_ios.mp4
company_cards_width_behavior_ios.mp4
dangerous_buttons_lock_account_ios.mp4
disabled_buttons_alt_action_hr_ios.mp4
multiple_states_buttons_down_upgrade_ios.mp4
status_activityindicator_behavior_ios.mp4
tax_value_button_plain_ios.mp4
iOS: mWeb Safari
add_delegate_offline_behavior_ios_web.mp4
company_cards_width_behavior_ios_web.mp4
dangerous_buttons_lock_account_ios_web.mp4
disabled_buttons_alt_action_hr_ios_web.mp4
multiple_states_buttons_down_upgrade_ios_web.mp4
status_activityindicator_behavior_ios_web.mp4
tax_value_button_plain_ios_web.mp4
MacOS: Chrome / Safari
add_delegate_offline_behavior_web.mp4
buttons_admin_action_hr_web.mp4
company_cards_width_behavior_web.mp4
dangerous_buttons_lock_account_web.mp4
disabled_buttons_alt_action_hr_web.mp4
multiple_states_buttons_down_upgrade_web.mp4
status_activityindicator_behavior_web.mp4
tax_value_button_plain_web.mp4