Skip to content

Book Travel enablement flow has no progress stepper #95692

Open
linhvovan29546 wants to merge 25 commits into
Expensify:mainfrom
linhvovan29546:travel-dynamic-stepper-95649
Open

Book Travel enablement flow has no progress stepper #95692
linhvovan29546 wants to merge 25 commits into
Expensify:mainfrom
linhvovan29546:travel-dynamic-stepper-95649

Conversation

@linhvovan29546

@linhvovan29546 linhvovan29546 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

This PR rebuilds the "Book Travel" workspace-enablement flow as a single dynamic multi-step flow with a progress stepper, replacing the old chain of separate full-screen pages.

New flow (travel/enable/:policyID/:subPage?/:action?, src/pages/Travel/EnableTravel/):

  • Built on useSubPage + InteractiveStepSubPageHeader, so each step is URL-addressable and survives web refresh.
  • The step list is computed from what the workspace/account still needs: Legal name (missing legal name), Verify account (unvalidated account), Domain selector (>1 admin private domain, not provisioned), Workspace address (no address, not provisioned), Tax ID (non-USD currency, not provisioned, no stored tax ID), and always Terms last. Single-step flows (only Terms) hide the progress bar.
  • The step list is frozen per flow session in TRAVEL_PROVISIONING.enabledSteps. Each step transition is a separate navigation push (a fresh mount), and completing a step flips the very Onyx flag that decided the step was included — without freezing, the step count would shrink out from under the user mid-flow (e.g. the legal name step vanishing after saving it and navigating back). The flow-entry mount (no subPage in the URL yet) always recomputes and overwrites the persisted list, so a stale list from an abandoned session is never trusted.
  • Edit mode is only enabled for stepper-dot presses coming from the last step (where every earlier step is complete by definition). From a mid-flow step, tapping a completed dot is plain navigation — otherwise edit mode's "Next jumps to the last step" behavior would skip steps the user hasn't filled in yet.
  • updateLegalName gained a shouldGoBack param: the standalone legal-name page still navigates back on save, but the stepper drives its own forward navigation, and the old built-in goBack() raced with the stepper's push causing a visible flash.

Removed pages/routes (the old per-screen flow is unreachable now that BookTravelButton routes to the stepper):

Deleted page Old route Ported to
DynamicDomainSelectorPage.tsx domain-selector (dynamic suffix) subPages/DomainSelectorStep.tsx
WorkspaceAddressForTravelPage.tsx travel/:domain/workspace-address subPages/WorkspaceAddressStep.tsx
TravelLegalEntityTaxIDPage.tsx travel/:domain/legal-entity-tax-id subPages/TaxIDStep.tsx
DynamicTravelTerms.tsx terms/:domain/accept/:policyID? subPages/TermsStep.tsx

Each step keeps the old page's form/UI and submit logic. What was intentionally not carried over into the steps: the per-page screen chrome (ScreenWrapper/HeaderWithBackButton/AccessOrNotFoundWrapper, now provided once by the stepper shell) and the hardcoded cross-screen routing — the OTP-validate-first gates and "where to go next" branching (setTravelProvisioningNextStep, getTravelAcceptTermsRoute) — which the stepper's computed step list replaces (account verification is its own step, and each step just calls onNext()).

No OldRoutes redirects were added for the deleted routes: a grep of the repo found no hardcoded references to them, they were client-driven wizard targets (not backend-generated links, unlike magic-code links which go through VERIFY_ACCOUNT — kept), and two of them carried policyID as a query param which OldRoutes.ts can't rewrite into the new path anyway. A stale bookmarked URL shows Not Found, and re-entering via Book travel resumes at the correct step with no data loss, since the stepper derives the steps from the same persisted state the old pages read.

Unchanged (per the issue's explicit constraints):

  • The legacy request-access path (IS_TRAVEL_VERIFIED beta off), all BookTravelButton pre-checks (blocked-feature beta, phone/SMS login, public domain, no admin domains, upgrade, non-paid workspace, already-enabled → TravelDot), the AcceptSpotnanaTerms API command/params, WorkspaceTravelInvoicingSection, and VerifyAccountPage for the legacy path.

Unit tests cover the step composition per condition, the frozen step list across remounts, the stale-session overwrite on flow entry, and the Tax ID step.

Fixed Issues

$ #95649
PROPOSAL: N/A

Tests

Prerequisites: an account with the IS_TRAVEL_VERIFIED beta on, admin of a paid group workspace that is not yet provisioned for travel. To vary the step conditions: clear/fill your legal name (Settings → Profile → Personal details), use an unvalidated vs. validated account, set/clear the workspace address (Workspace → Overview), and switch the workspace currency to non-USD (e.g. GBP) to exercise the Tax ID step.

  1. Clear your legal name, then click Book travel (workspace Travel section)
  2. Verify the enablement stepper opens on the Legal name step, with a progress bar showing one dot per needed step (Terms always last)
  3. Submit a legal name and verify the flow advances to the next step, the completed step shows a checkmark, and the total dot count does not change
  4. Press the header back button on a later step and verify it returns to the previous step; on the first step, verify it closes the flow
  5. From a mid-flow step (e.g. Workspace address), tap the completed Legal name dot, then press Next — verify the flow continues sequentially to the following step (it must not jump to Terms and skip unfilled steps)
  6. Walk forward to the Terms step, tap a completed dot, re-save that step, and verify Next returns you straight to Terms
  7. Verify step composition per condition: Verify account appears only for an unvalidated account, Domain selector only with more than one admin private email domain, Workspace address only when the workspace has no address, Tax ID only for a non-USD workspace with no stored tax ID. When nothing is needed, verify the flow lands directly on Terms with no progress bar
  8. On web, refresh mid-flow and verify you stay on the same step (the step is in the URL)
  9. On the Terms step, verify Continue is disabled until the checkbox is checked; accept the terms and verify the flow closes and TravelDot opens
  10. Turn the IS_TRAVEL_VERIFIED beta off and verify Book Travel uses the old request-access path (no stepper); verify the pre-checks still fire before the stepper (public-domain email → error screen, phone/SMS login → inline error, no paid workspace → upgrade screen, terms already accepted → TravelDot directly)
  • Verify that no errors appear in the JS console

Offline tests

Same as the Tests section above.

QA Steps

Prerequisites: an account with the IS_TRAVEL_VERIFIED beta on, admin of a paid group workspace that is not yet provisioned for travel. To vary the step conditions: clear/fill your legal name (Settings → Profile → Personal details), use an unvalidated vs. validated account, set/clear the workspace address (Workspace → Overview), and switch the workspace currency to non-USD (e.g. GBP) to exercise the Tax ID step.

  • Verify the enablement stepper opens on the Legal name step, with a progress bar showing one dot per needed step (Terms always last)

  • Submit a legal name and verify the flow advances to the next step, the completed step shows a checkmark, and the total dot count does not change

  • Press the header back button on a later step and verify it returns to the previous step; on the first step, verify it closes the flow

  • From a mid-flow step (e.g. Workspace address), tap the completed Legal name dot, then press Next — verify the flow continues sequentially to the following step (it must not jump to Terms and skip unfilled steps)

  • Walk forward to the Terms step, tap a completed dot, re-save that step, and verify Next returns you straight to Terms

  • Verify step composition per condition: Verify account appears only for an unvalidated account, Domain selector only with more than one admin private email domain, Workspace address only when the workspace has no address, Tax ID only for a non-USD workspace with no stored tax ID. When nothing is needed, verify the flow lands directly on Terms with no progress bar

  • On web, refresh mid-flow and verify you stay on the same step (the step is in the URL)

  • On the Terms step, verify Continue is disabled until the checkbox is checked; accept the terms and verify the flow closes and TravelDot opens

  • Turn the IS_TRAVEL_VERIFIED beta off and verify Book Travel uses the old request-access path (no stepper); verify the pre-checks still fire before the stepper (public-domain email → error screen, phone/SMS login → inline error, no paid workspace → upgrade screen, terms already accepted → TravelDot directly)

  • 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 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 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)
  • 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)
  • 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.
  • 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
telegram-cloud-document-5-6249039001768959679.mp4
Android: mWeb Chrome
telegram-cloud-document-5-6249039001768959680.mp4
iOS: Native
Screen.Recording.2026-07-15.at.11.53.49.mov
iOS: mWeb Safari
Screen.Recording.2026-07-15.at.11.21.58.mov
MacOS: Chrome / Safari
Screen.Recording.2026-07-15.at.11.08.08.mov

blimpich and others added 6 commits July 9, 2026 17:39
- TermsStep: use current expensify-common Str import
- VerifyAccountStep: use lastValidateCodeRequestedAt hydration guard
  (validateCodeSent no longer exists) and match current
  validateSecondaryLogin(contactMethod, validateCode) signature
… stepper

BookTravelButton now hands off entirely to the new EnableTravel stepper for
self-serve provisioning, so the old cascade of standalone screens (domain
selector, workspace address, legal-entity tax ID, terms) and the
nextStepRoute hand-off mechanism they relied on are dead code. Simplify
VerifyAccountPage to drop its now-unreachable self-serve forward-navigation
branch (kept only for the legacy beta-off request-access path).

Also fixes a real bug in the ported stepper: WorkspaceAddressStep's country
picker navigates through the ADDRESS_COUNTRY dynamic route, which is gated
by an entryScreens allowlist that didn't include the new stepper's screen -
country selection would have silently failed. Also carries forward a terms
error-handling fix that landed on main after the reference branch was cut
(clearing the provisioning session before showing the verify-company modal).
EnableTravelContentTest verifies the core acceptance criteria: the step
count reflects only what a given workspace actually needs (single-step
flows hide the progress bar, provisioned workspaces skip domain/address/tax
ID regardless of currency or admin domain count, unprovisioned non-USD
workspaces with multiple domains and no address need every step).

TaxIDStepTest replaces the coverage lost when TravelLegalEntityTaxIDPageTest
was deleted along with the old standalone tax ID page.
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

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/CONST/index.ts 94.81% <ø> (ø)
src/SCREENS.ts 100.00% <ø> (ø)
src/libs/Navigation/linkingConfig/config.ts 76.92% <ø> (ø)
src/libs/actions/PersonalDetails.ts 46.61% <100.00%> (+0.92%) ⬆️
...c/pages/Travel/EnableTravel/subPages/TaxIDStep.tsx 100.00% <100.00%> (ø)
...gation/AppNavigator/ModalStackNavigators/index.tsx 6.53% <0.00%> (+0.02%) ⬆️
...ges/Travel/EnableTravel/subPages/LegalNameStep.tsx 95.65% <95.65%> (ø)
src/pages/Travel/VerifyAccountPage.tsx 0.00% <0.00%> (ø)
src/ROUTES.ts 21.14% <60.00%> (-0.02%) ⬇️
src/components/BookTravelButton.tsx 82.43% <80.00%> (+6.57%) ⬆️
... and 7 more
... and 77 files with indirect coverage changes

- DomainSelectorStep: migrate from the deprecated default Button import
  to the composed ButtonComposed API (no-restricted-imports)
- EnableTravelContentTest: use computed object keys for admin email test
  fixtures instead of literal email-like property names, and disable
  no-unsafe-type-assertion for the require() casts in the RenderHTML mock
  (matching the pattern used elsewhere in this test suite)
- Reword "unprovisioned" to "not-yet-provisioned" in a comment and a test
  name; cspell doesn't recognize the un- prefixed form
…pper

Each step in the enablement stepper is a separate navigation push (a fresh
mount, not an in-place update), and completing a step flips the very Onyx
flag that decided whether that step was included. Recomputing the step list
on every mount caused the total step count to shrink as the user progressed,
and made going back land on a mount with a mismatched step list.

Persist the frozen step list to TRAVEL_PROVISIONING.enabledSteps instead,
matching the existing pattern for other cross-step state in this flow
(domain, taxID) - it's computed once on the first step and read back on
every subsequent mount instead of recomputed, and reset by
cleanupTravelProvisioningSession() at the start of every fresh session.

Also fixes a regression introduced while chasing this: gating the whole
screen on travelProvisioning's own loading metadata could leave it stuck on
the loading indicator, since it's a plain optional session key with no
guaranteed write on account creation. EnableTravelContent already treats
"not loaded yet" and "no persisted enabledSteps" the same way, so the screen
no longer waits on it.
…illed steps

Restore the enabledSteps session snapshot on TRAVEL_PROVISIONING that the
flash fix accidentally removed: each step is a fresh mount, so recomputing
the step list per mount made completed steps vanish (e.g. legal name after
back + Next). The list is frozen per flow session again, and hardened: the
flow-entry mount (no subPage param yet) always recomputes and overwrites
whatever is persisted, so a stale list from an abandoned session is never
trusted.

Also only turn on edit mode for stepper-dot presses coming from the last
step. From any earlier step a dot press is plain navigation now, since
edit mode's Next jumps straight to the last step and would skip steps the
user hasn't filled in yet (address could be bypassed entirely).
@linhvovan29546
linhvovan29546 marked this pull request as ready for review July 11, 2026 10:18
@linhvovan29546
linhvovan29546 requested review from a team as code owners July 11, 2026 10:18
@melvin-bot
melvin-bot Bot requested review from heyjennahay and huult and removed request for a team July 11, 2026 10:18
@melvin-bot

melvin-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown
Contributor

This PR adds a new Onyx.connectWithoutView call, so I've requested a review from the Onyx performance reviewers (@tgolen, @mountiny, @luacmartins) — a review from any one of them is enough. Please add a link in your PR description to the Slack discussion where the @frontend-performance team approved using connectWithoutView here.

@linhvovan29546

Copy link
Copy Markdown
Contributor Author

This should be ready for the first round of review. I'm still recording screenshots to complete the PR author checklist

@linhvovan29546

Copy link
Copy Markdown
Contributor Author

This PR adds a new Onyx.connectWithoutView call, so I've requested a review from the Onyx performance reviewers (@tgolen, @mountiny, @luacmartins) — a review from any one of them is enough. Please add a link in your PR description to the Slack discussion where the @frontend-performance team approved using connectWithoutView here.

connectWithoutView is only used in the test file tests/ui/EnableTravelContentTest.tsx

@linhvovan29546

Copy link
Copy Markdown
Contributor Author

This PR adds a new Onyx.connectWithoutView call, so I've requested a review from the Onyx performance reviewers

Same as #95692 (comment)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d6f8a5a89b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment thread src/pages/Travel/EnableTravel/subPages/VerifyAccountStep.tsx
@blimpich

Copy link
Copy Markdown
Contributor

Removing onyx expert review based off this comment

@blimpich
blimpich requested a review from shawnborton July 15, 2026 17:55
@blimpich

Copy link
Copy Markdown
Contributor

Adding Shawn as a reviewer. @shawnborton as a reminder this PR is a result of this thread where we decided to make the travel enablement flow into a dynamic stepper. Can you look at the screenshots / videos to make sure it looks the way you thought it would?

@huult

huult commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible 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 checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • 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 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)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • 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 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.
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this 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.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
Android: mWeb Chrome
iOS: HybridApp
iOS: mWeb Safari
MacOS: Chrome / Safari

@shawnborton

Copy link
Copy Markdown
Contributor

Ideally every step has the big headline treatment for consistency - looks like step 2 doesn't have one:
CleanShot 2026-07-16 at 09 13 30@2x

Can we make sure we have consistent bottom padding on the stepper for each step, using what we already have elsewhere?
CleanShot 2026-07-16 at 09 14 24@2x

@shawnborton

Copy link
Copy Markdown
Contributor

There is an awkward delay after you confirm the centered modal and then it takes a moment for the RHP to close. Can that all close at the same time?

CleanShot.2026-07-16.at.09.15.22.mp4

@huult

huult commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@linhvovan29546 Could you help review the comment above?

@huult

huult commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-07-17 at 14 41 33

@linhvovan29546 Could you merge main into your branch to fix this issue?

Confirming the verify-company modal only resolved once its own dismiss
animation finished, so the RHP close it triggers played strictly after
the modal had already fully closed. Resolve immediately on tap and
close the modal explicitly once the RHP-close/navigate kicks off, so
both happen together instead of one waiting on the other.
@github-actions

Copy link
Copy Markdown
Contributor

This PR adds a new Onyx.connectWithoutView call, so I've requested a review from the Onyx performance reviewers (@tgolen, @mountiny, @luacmartins) — a review from any one of them is enough. Please add a link in your PR description to the Slack discussion where the @frontend-performance team approved using connectWithoutView here.

@linhvovan29546

Copy link
Copy Markdown
Contributor Author

There is an awkward delay after you confirm the centered modal and then it takes a moment for the RHP to close. Can that all close at the same time?

Fixed

Screen.Recording.2026-07-17.at.14.52.34.mov

@linhvovan29546

Copy link
Copy Markdown
Contributor Author

Can we make sure we have consistent bottom padding on the stepper for each step, using what we already have elsewhere?

Fixed
Screenshot 2026-07-17 at 14 28 50

@huult

huult commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
Screen.Recording.2026-07-17.at.15.04.06.mov

BUG:

When I open the Travel page and reload it, I'm unexpectedly redirected to the Workspace report chat in the background.

@huult

huult commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Clear your legal name, then click Book travel (workspace Travel section)

@linhvovan29546 How can we clear the legal name?

@linhvovan29546

Copy link
Copy Markdown
Contributor Author

Ideally every step has the big headline treatment for consistency - looks like step 2 doesn't have one:

Currently, only the Legal page and the Terms step have a big headline. I reused the existing pages, so the other steps don't have one. Could you please provide the headline you want for each step?

I've attached the images below. These pages don't have a big headline.

Screenshot 2026-07-17 at 15 09 00 Screenshot 2026-07-17 at 15 08 10 Screenshot 2026-07-17 at 15 09 43 Screenshot 2026-07-17 at 15 06 56

@linhvovan29546

Copy link
Copy Markdown
Contributor Author

Clear your legal name, then click Book travel (workspace Travel section)

@linhvovan29546 How can we clear the legal name?

Run the following command in the console to clear the legal name:

Onyx.merge('private_personalDetails', {
    legalFirstName: '',
    legalLastName: '',
});

…Test

This is a one-shot read in a test helper, not a React view, so the
connectWithoutView/connect distinction doesn't apply - other tests
(AttachmentTest, DelegateTest, etc.) already use plain connect() for
this. connectWithoutView also unconditionally re-triggers the Onyx
performance-reviewer request workflow on every push for the life of
the PR, regardless of relevance.
@linhvovan29546

Copy link
Copy Markdown
Contributor Author

When I open the Travel page and reload it, I'm unexpectedly redirected to the Workspace report chat in the background.

I can fix this by using DYNAMIC_ROUTES, similar to what you already did in MissingPersonalDetailsContent. However, I noticed that useSubPage has shouldReplaceRoute set to true, which causes each transition to replace the current route. As a result, clicking the browser's Back button closes the page instead of back to the previous steps.

@shawnborton shawnborton added the Waiting for copy User facing verbiage needs polishing label Jul 17, 2026
@shawnborton

Copy link
Copy Markdown
Contributor

Could you please provide the headline you want for each step?

I think we can do something like:

  • Validate your account to enable this feature
  • Choose a domain for Expensify Travel setup
  • Add your address
  • Enter your legal entity tax ID

But let's see what @Expensify/marketing thinks (cc @jamesdeanexpensify - waiting for copy label doesn't work on PRs?)

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

Labels

Waiting for copy User facing verbiage needs polishing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants