You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-03-30] Reports - Keyboard navigation does not work at the first/last item of Column list #85657
Version Number: 9.3.40-0 Reproducible in staging?: Yes Reproducible in production?: N/A - new feature, doesn't exist in prod If this was caught during regression testing, add the test name, ID and link from BrowserStack:#78869 Email or phone of affected tester (no customers):sjodinjsonjinodisjniod@gmail.com Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Mac 26.2 / Chrome App Component: Search
Action Performed:
Go to staging.new.expensify.com
Go to Reports > Expenses.
Click Columns.
Press Up arrow key.
Press Down arrow key until the last item in the list.
Press Down arrow key again.
Expected Result:
Pressing Up arrow key at the top of the list will focus on the last item in the list.
Pressing Down arrow key at the last item of the list will focus on the first item in the list.
Actual Result:
Pressing Up arrow key at the top of the list does not navigate.
Pressing Down arrow key at the last item of the list does not navigate.
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
Identify the pull request that introduced this issue and revert it.
Classification: Frontend bug Causing PR: #78869 - "fix: Arrow key navigation not working in Columns selection" by @TaduJR (High confidence) Related Issues: None
Recommendation: REVERT
The PR should be reverted. It intentionally disabled cyclic keyboard navigation, but the expected behavior is that arrow keys should wrap around at list boundaries.
Labels: No changes needed. DeployBlockerCash is correctly applied (frontend bug in App repository).
Direct code match: The bug symptoms (no wrap-around navigation) exactly match the implementation in the PR
Intentional design choice: In src/hooks/useListKeyboardNav.ts line 44, the PR sets disableCyclicTraversal: true
Verification
Files affected by the bug:
/home/runner/_work/App/App/src/components/ColumnsSettingsList.tsx - The Columns settings UI where the bug manifests
/home/runner/_work/App/App/src/hooks/useListKeyboardNav.ts - New hook added by the PR that controls keyboard navigation
Confirmed PR modifies these files:
✅ src/components/ColumnsSettingsList.tsx - Modified to integrate keyboard navigation
✅ src/hooks/useListKeyboardNav.ts - New file added by the PR
✅ src/hooks/useArrowKeyFocusManager.ts - Used by the new hook
Root Cause
The PR added keyboard navigation support to DraggableList/ColumnsSettingsList using a new useListKeyboardNav hook. This hook calls useArrowKeyFocusManager with disableCyclicTraversal: true (line 44 of useListKeyboardNav.ts).
When disableCyclicTraversal is true:
Pressing Up arrow at the first item returns the current index (no-op) instead of wrapping to the last item
Pressing Down arrow at the last item returns the current index (no-op) instead of wrapping to the first item
However, the expected behavior (per the bug report) is that navigation should wrap cyclically at both ends of the list. The PR implementation contradicts this expectation.
Please re-state the problem that we are trying to solve in this issue.
When using keyboard navigation (arrow keys) in the Columns settings dropdown (Search > Reports > Expenses > Columns), pressing the Up arrow at the top of the list does not cycle to the last item, and pressing the Down arrow at the last item does not cycle to the first item. The arrow keys simply stop working at the boundaries.
What is the root cause of that problem?
In src/hooks/useListKeyboardNav.ts, the hook passes disableCyclicTraversal: true to useArrowKeyFocusManager (line 44). This flag explicitly prevents wrapping at list boundaries:
ArrowUp at index 0:useArrowKeyFocusManager sets nextIndex = -1 (instead of maxIndex), which triggers the disableCyclicTraversal guard and returns the current index unchanged — a no-op.
ArrowDown at last index:nextIndex is set to maxIndex (instead of 0), so currentFocusedIndex stays at the same value — also a no-op.
The useArrowKeyFocusManager hook already supports cyclic traversal when disableCyclicTraversal is false (the default). The issue is that useListKeyboardNav explicitly opts out of it.
What changes do you think we should make in order to solve the problem?
Remove the disableCyclicTraversal: true option from useListKeyboardNav.ts (line 44). Since false is the default value for disableCyclicTraversal in useArrowKeyFocusManager, simply removing this line will enable cyclic traversal — ArrowUp at the first item will wrap to the last, and ArrowDown at the last item will wrap to the first.
Additionally, add boundary test cases to tests/unit/useListKeyboardNavTest.ts to verify wrapping behavior (ArrowUp at index 0 should focus the last item, ArrowDown at the last index should focus the first item).
What alternative solutions did you explore? (Optional)
An alternative would be to make disableCyclicTraversal a configurable parameter on useListKeyboardNav so individual consumers can choose. However, since the issue specifically requests cyclic behavior and there's currently only one consumer (ColumnsSettingsList), the simpler fix of just removing the flag is preferred.
Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, @MelvinBot <your feedback> to refine this analysis, or explain why you are rejecting Melvin's proposal.
@aimane-chnaif The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]
I don't have access to Upwork, so I can't verify whether job offers were actually created there. However, based on what's visible in this issue:
No automated Upwork offers were created for either contributor. The deployment comment from melvin-bot explicitly flagged both as needing manual action:
@TaduJR requires payment (Needs manual offer from BZ)
@aimane-chnaif requires payment (Needs manual offer from BZ)
The Payment Summary also has empty Upwork job links ([Upwork Job]()) and placeholder amounts ($(AMOUNT)), which indicates the offers haven't been filled in yet.
Why not? The "Needs manual offer from BZ" flag means the automated system couldn't create Upwork offers for these contributors — this typically happens when the contributors aren't set up for automatic Upwork job creation (e.g., no linked Upwork profile in the system, or the issue/PR didn't follow the standard automated payment flow). Both offers need to be manually created by the BZ manager (mallenexpensify).
Activity
melvin-bot commentedon Mar 18, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #78869
melvin-bot commentedon Mar 18, 2026
💬 A slack conversation has been started in #expensify-open-source
github-actions commentedon Mar 18, 2026
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
OSBotify commentedon Mar 18, 2026
🔍 Investigation Summary
Classification: Frontend bug
Causing PR: #78869 - "fix: Arrow key navigation not working in Columns selection" by @TaduJR (High confidence)
Related Issues: None
Recommendation: REVERT
The PR should be reverted. It intentionally disabled cyclic keyboard navigation, but the expected behavior is that arrow keys should wrap around at list boundaries.
Labels: No changes needed.
DeployBlockerCashis correctly applied (frontend bug in App repository).📋 Detailed Analysis
Evidence
src/hooks/useListKeyboardNav.tsline 44, the PR setsdisableCyclicTraversal: trueVerification
Files affected by the bug:
/home/runner/_work/App/App/src/components/ColumnsSettingsList.tsx- The Columns settings UI where the bug manifests/home/runner/_work/App/App/src/hooks/useListKeyboardNav.ts- New hook added by the PR that controls keyboard navigationConfirmed PR modifies these files:
src/components/ColumnsSettingsList.tsx- Modified to integrate keyboard navigationsrc/hooks/useListKeyboardNav.ts- New file added by the PRsrc/hooks/useArrowKeyFocusManager.ts- Used by the new hookRoot Cause
The PR added keyboard navigation support to DraggableList/ColumnsSettingsList using a new
useListKeyboardNavhook. This hook callsuseArrowKeyFocusManagerwithdisableCyclicTraversal: true(line 44 of useListKeyboardNav.ts).When
disableCyclicTraversalis true:However, the expected behavior (per the bug report) is that navigation should wrap cyclically at both ends of the list. The PR implementation contradicts this expectation.
MelvinBot commentedon Mar 18, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When using keyboard navigation (arrow keys) in the Columns settings dropdown (Search > Reports > Expenses > Columns), pressing the Up arrow at the top of the list does not cycle to the last item, and pressing the Down arrow at the last item does not cycle to the first item. The arrow keys simply stop working at the boundaries.
What is the root cause of that problem?
In
src/hooks/useListKeyboardNav.ts, the hook passesdisableCyclicTraversal: truetouseArrowKeyFocusManager(line 44). This flag explicitly prevents wrapping at list boundaries:useArrowKeyFocusManagersetsnextIndex = -1(instead ofmaxIndex), which triggers thedisableCyclicTraversalguard and returns the current index unchanged — a no-op.nextIndexis set tomaxIndex(instead of0), socurrentFocusedIndexstays at the same value — also a no-op.The
useArrowKeyFocusManagerhook already supports cyclic traversal whendisableCyclicTraversalisfalse(the default). The issue is thatuseListKeyboardNavexplicitly opts out of it.What changes do you think we should make in order to solve the problem?
Remove the
disableCyclicTraversal: trueoption fromuseListKeyboardNav.ts(line 44). Sincefalseis the default value fordisableCyclicTraversalinuseArrowKeyFocusManager, simply removing this line will enable cyclic traversal — ArrowUp at the first item will wrap to the last, and ArrowDown at the last item will wrap to the first.Additionally, add boundary test cases to
tests/unit/useListKeyboardNavTest.tsto verify wrapping behavior (ArrowUp at index 0 should focus the last item, ArrowDown at the last index should focus the first item).What alternative solutions did you explore? (Optional)
An alternative would be to make
disableCyclicTraversala configurable parameter onuseListKeyboardNavso individual consumers can choose. However, since the issue specifically requests cyclic behavior and there's currently only one consumer (ColumnsSettingsList), the simpler fix of just removing the flag is preferred.Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR,@MelvinBot <your feedback>to refine this analysis, or explain why you are rejecting Melvin's proposal.TaduJR commentedon Mar 18, 2026
I think this is expected.
WDYT @aimane-chnaif?
aimane-chnaif commentedon Mar 18, 2026
I thought this is expected while testing. But now I see different behavior on SelectionList.
16 remaining items
melvin-bot commentedon Mar 23, 2026
@aimane-chnaif The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]
melvin-bot commentedon Mar 23, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)melvin-bot commentedon Mar 30, 2026
Payment Summary
Upwork Job
BugZero Checklist (@mallenexpensify)
melvin-bot commentedon Mar 30, 2026
Payment Summary
Upwork Job
BugZero Checklist (@mallenexpensify)
mallenexpensify commentedon Mar 31, 2026
@MelvinBot were job offers created in Upwork for both @aimane-chnaif and @TaduJR on this issue? if not, why not?
MelvinBot commentedon Mar 31, 2026
I don't have access to Upwork, so I can't verify whether job offers were actually created there. However, based on what's visible in this issue:
No automated Upwork offers were created for either contributor. The deployment comment from melvin-bot explicitly flagged both as needing manual action:
The Payment Summary also has empty Upwork job links (
[Upwork Job]()) and placeholder amounts ($(AMOUNT)), which indicates the offers haven't been filled in yet.Why not? The "Needs manual offer from BZ" flag means the automated system couldn't create Upwork offers for these contributors — this typically happens when the contributors aren't set up for automatic Upwork job creation (e.g., no linked Upwork profile in the system, or the issue/PR didn't follow the standard automated payment flow). Both offers need to be manually created by the BZ manager (
mallenexpensify).mallenexpensify commentedon Mar 31, 2026
@TaduJR @aimane-chnaif can you please accept the job below? Please reply here and tag me once you have.
https://www.upwork.com/jobs/~022038769096114803386
@TaduJR @aimane-chnaif were either of you sent offers in Upwork?
I need to fix the bug cuz it takes me a lot longer to pay y'all each time this happens
TaduJR commentedon Mar 31, 2026
@mallenexpensify
No Automatic offer sent on my side
Payment is not needed here.
TaduJR commentedon Mar 31, 2026
We can close this.
mallenexpensify commentedon Apr 1, 2026
ugggh, forgot to reduce pay in the parent issue for this regression, commented there