Gate company card and Expensify Card feed selection behind a Save button (a11y On Input, PR 9) - #99240
Gate company card and Expensify Card feed selection behind a Save button (a11y On Input, PR 9)#99240MelvinBot wants to merge 1 commit into
Conversation
…ton (a11y On Input, PR 9) Co-authored-by: truph01 <truph01@users.noreply.github.com>
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
🤖 Web testing — blocked on account dataI could not live-verify the Save-gated feed selectors on Web. The change lives at Workspace → Company cards and Workspace → Expensify Card, but the CI test account has no workspace at all (the Workspaces tab shows "No workspaces yet"), so neither feed-selector page is reachable. Even creating a fresh workspace wouldn't help: a new workspace has zero company-card and zero Expensify Card feeds connected (that needs a real bank/card connection), so there'd still be no feed rows to stage/select between. What I could not verify (needs a workspace with ≥1 feed per surface):
Code-level corroboration (read-only, not a live test)The PR code implements exactly the described behavior on both pages:
This confirms the logic is wired as intended, but it is not a substitute for the live UI verification above. To get a full Web pass, this needs a test account/session pre-provisioned with a workspace that already has ≥1 company-card feed and ≥1 Expensify Card feed connected so the feed selector actually renders. Happy to re-run once such an account is available. |
|
@MelvinBot Mark this PR as ready |
|
🤖 Done — this PR is now marked Ready for review (out of draft). |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4d8f57d164
ℹ️ 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".
| const selectFeed = (feed: ExpensifyFeedListItem) => { | ||
| setDraftFundID(feed.value); | ||
| }; |
There was a problem hiding this comment.
Apply the draft before starting card issuance
When multiple primary feeds exist, selecting feed B now only updates draftFundID, but the still-visible Issue card footer continues to derive issueCardFundID from lastSelectedExpensifyCardFeedID. If the user selects B and then taps Issue card without first pressing Save, handleAddCardPress writes the old feed A back to Onyx, and the issuance flow uses that old feed via useDefaultFundID, potentially issuing the card under the wrong program. Derive this footer action from currentSelectedFundID or disable it until the draft has been saved.
Useful? React with 👍 / 👎.
|
I looked into the two failing checks — neither is a code problem, so there's nothing for me to push a fix for.
Both are process gates that only a human reviewer can satisfy — they're on the standard ignore list precisely because they can't be resolved with a code change. Every actual code/build/test check (ESLint, Oxfmt, typecheck, React Compiler, Storybook, Bun/unit tests, perf, builds) is green ✅. No commit was pushed. |
|
Same situation as my previous comment — the only two red checks are human-only process gates, not anything I can fix with code:
Every actual code/build/test check is green ✅. There's no code failure here, so I haven't pushed anything. These will resolve on their own once a reviewer approves and fills out the checklist. |



Explanation of Change
This addresses a WCAG 3.2.2 "On Input" accessibility violation, part of the batched plan in issue #74834 (PR 9). These two near-identical feed selectors committed the selected feed and navigated back the instant a row was tapped, so the layout/context changed without the user explicitly confirming — disorienting for screen-reader and low-vision users.
Both pages now stage the tapped main feed in local state and only commit it when the user presses the Save button (via
confirmButtonOptionsonSelectionList), matching the pattern already shipped in PRs 2–8. The staged row is highlighted, and the Save button is disabled until the staged selection differs from the current feed. Per the plan, only the main feed selection is gated behind Save — the footer rows are left immediate because they kick off async link/verify flows:WorkspaceCompanyCardFeedSelectorPage—selectFeedstages; Save runsupdateSelectedFeed+goBack. The "Add cards" and "from other workspaces" footer rows (selectOtherFeed, which links/verifies and may navigate to add/verify-work-email) stay immediate.WorkspaceExpensifyCardFeedSelectorPage—selectFeedstages; Save runsresetCardFlowState+updateSelectedExpensifyCardFeed+goBack. The "Issue card / Set up new program" and "from other workspaces" footer rows stay immediate. The empty-stateScrollView(no primary feeds) is unchanged.🤖 Generated by MelvinBot. Checks run locally:
lint-changed✅,typecheck-tsgo✅. React Compiler compliance check couldn't run in this environment (base-ref resolution); no manual memoization was added, so CI will validate. Fullnpm test/ storybook smoke deferred to CI.Fixed Issues
$ #74834
PROPOSAL: #74834 (comment)
Tests
Offline tests
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
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
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari