Skip to content

[Due for payment 2026-10-01] Expense - Cursor appears briefly on list report field after clicking on it #101804

Closed

Description

@applause-bot

If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.


Version Number: 9.4.91-0
Reproducible in staging?: Yes
Reproducible in production?: No
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #100735
Email or phone of affected tester (no customers): sjodjoijsonjoinj@gmail.com
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: Mac 26.5 / Chrome
App Component: Money Requests

Action Performed:

Precondition:

  • Create a list type report field
  1. Go to staging.new.expensify.com
  2. Go to workspace chat.
  3. Create an expense.
  4. Open the expense.
  5. Click on the list report field.

Expected Result:

Cursor will not appear on list report field because it does not support text input.

Actual Result:

Cursor appears briefly on list report field after clicking on it.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome Safari

Screenshots/Videos

Bug7265678_1790019363733.5.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Svetlana Lazutkina
Bug ID: 7265678

Issue OwnerCurrent Issue Owner: @daledah

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    on Sep 21, 2026
  2. applause-bot commented on Sep 21, 2026

    @applause-bot
    Author

    While Applause doesn't embed attachments for this bug, here are the links for quick view:
    https://platform.applause.com/services/links/v1/external/f9d9348972ae0817ba16a9890a7dcc2dc9bc2118069e07e52231c9b6131c2190

  3. melvin-bot commented on Sep 21, 2026

    @melvin-bot

    You have been assigned to this deploy blocker because you recently merged this PR: #100735

  4. github-actions commented on Sep 21, 2026

    @github-actions
    Contributor

    👋 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:

    1. Identify the pull request that introduced this issue and revert it.
    2. Find someone who can quickly fix the issue.
    3. Fix the issue yourself.
  5. melvin-bot commented on Sep 21, 2026

    @melvin-bot

    @Gonals @daledah you have been assigned to this deploy blocker because you reviewed the offending PR: #100735

  6. melvin-bot commented on Sep 21, 2026

    @melvin-bot

    💬 A slack conversation has been started in #expensify-open-source

  7. MelvinBot commented on Sep 21, 2026

    @MelvinBot
    Contributor

    🔍 Investigation Summary

    Classification: Frontend bug
    Causing PR: #100735 - "Show up to three report fields per row and edit them inline" by @MelvinBot (High confidence)
    Related Issues: [$250] Report fields should be shown in a grid and editable inline (the issue the PR implements)

    Recommendation: ROLL FORWARD

    The regression is a one-prop omission in brand-new code (a list report field now renders a real web <input> that gets programmatically focused on press, with nothing hiding the caret), so a targeted fix is far smaller and safer than reverting a large, multi-file feature that also landed a shared useSaveReportField hook and DatePicker/EditReportFieldDropdown changes.

    Suggested fix — in ReportFieldInlineInput.tsx LIST branch, add caretHidden to the trigger TextInput. caretHidden maps to caret-color: transparent in react-native-web and is applied after inputStyle, so it cannot be overridden by the existing pointerEventsNone input style. Optionally also readOnly so the field can never receive typed input, and/or mirror the DatePicker approach of blurring the input when the popover opens.

    Assigned: @Gonals and @daledah (approving reviewers of the causing PR) — already assigned by Melvin; the PR author is @MelvinBot (bot), so there is no human author to add.
    Labels: No changes. DeployBlockerCash stays because an App PR caused this and the fix is in Expensify/App. No DeployBlocker label is present, so nothing was removed.

    📋 Detailed Analysis

    Evidence

    • Reproducible on staging 9.4.91-0, not on production — consistent with something in the current Deploy Checklist: New Expensify 2026-09-21.
    • Before #100735, a report field in the expense/report view was rendered as a MenuItemWithTopDescription row that navigated to the report field editor page. A menu item contains no text input at all, so a caret was structurally impossible there.
    • That PR removes MenuItemWithTopDescription from both MoneyRequestViewReportFields.tsx and MoneyReportView.tsx and replaces them with the new ReportFieldInlineInput, which renders a real TextInput for list-type fields.
    • The PR merged 2026-09-21 and is item 14 in the chronological list for 9.4.91-0; the bug was reported against that same build.
    • No other PR in the checklist could produce this symptom: the list-report-field input only exists because of this PR.

    Verification

    Affected files (all at merge commit 44bd04c):

    gh pr view 100735 --json files confirms ReportFieldInlineInput.tsx is added by this PR and that MoneyRequestViewReportFields.tsx / MoneyReportView.tsx are modified by it.

    Root Cause

    For a list field, ReportFieldInlineInput renders a TextInput as the dropdown trigger with role={CONST.ROLE.COMBOBOX}, inputStyle={styles.pointerEventsNone} and disableKeyboard, and onPress={onPress} from FilterPopupButton.

    Three things combine on web:

    1. BaseTextInput's press handler calls inputProps.onPress?.(event) and then, when the event's default was not prevented, input.current?.focus(). So the real DOM <input> is focused on click. inputStyle={styles.pointerEventsNone} only stops the mouse from reaching the input; it does not stop this programmatic focus.
    2. disableKeyboard on web only sets inputmode="none" (it suppresses the mobile virtual keyboard). It does not set readOnly and it does not hide the caret, so a focused desktop <input> blinks a caret.
    3. FilterPopupButton.calculatePopoverPositionAndToggleOverlay opens the popover asynchronously (KeyboardUtils.dismissKeyboardAndExecute → calculatePopoverPosition(...).then(...)), and unlike DatePicker — which calls textInputRef.current?.blur() as the first thing in showDatePickerModal — this branch never blurs the trigger. The caret is therefore visible for the window between the click and the popover mounting and taking focus, which is exactly the reported "appears briefly".

    The value is controlled and there is no onChangeText on this input, so nothing can actually be typed into the field — the impact is purely the visible caret.

    💡 Suggested AI code review rule

    This looks like a recurring, mechanically detectable pattern (any TextInput used purely as a press-to-open trigger has it), so it may be worth a coding-standards rule so the AI reviewer catches the next one. Proposed for Expensify/App (.claude/skills/app-coding-standards):

    • Rule: UI-4 — A TextInput used as a press-to-open trigger must hide its caret
    • Condition: When a TextInput is rendered as a non-typable trigger (it has onPress/disableKeyboard, role={CONST.ROLE.COMBOBOX}, or an inputStyle of pointerEventsNone and no onChangeText), it must also set caretHidden (and normally readOnly), or blur the input when the overlay opens. Do not rely on disableKeyboard or pointerEventsNone — on web the former only sets inputmode="none" and the latter does not prevent BaseTextInput from programmatically focusing the input on press.
    • Why: On web BaseTextInput's press handler focuses the real DOM <input>, so a field that accepts no text still shows a blinking caret until the popover steals focus. That shipped as deploy blocker Expense - Cursor appears briefly on list report field after clicking on it.
    • Search pattern: JSX <TextInput ... /> elements that have disableKeyboard or onPress= or role={CONST.ROLE.COMBOBOX} and no onChangeText, and that do not also pass caretHidden — e.g. rg -U '<TextInput[^>]*(disableKeyboard|ROLE\.COMBOBOX)' src/ --multiline then filter out matches containing caretHidden.
    • Offending code (❌): ReportFieldInlineInput.tsx#L203-L220
    • Fix (✅): add caretHidden to that same TextInput; the existing blur-on-open precedent is DatePicker/index.tsx#L117-L121

    The full rule file, with the ❌/✅ code inline in the App app-coding-standards format, would go in Expensify/App itself. If it's worth adding, a maintainer can open it there as a draft PR.

  8. melvin-bot commented on Sep 21, 2026

    @melvin-bot

    ⚠️ Looks like this issue was linked to a Deploy Blocker here

    If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

    If a regression has occurred and you are the assigned CM follow the instructions here.

    If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

  9. melvin-bot commented on Sep 21, 2026

    @melvin-bot

    ⚠️ Looks like this issue was linked to a Deploy Blocker here

    If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

    If a regression has occurred and you are the assigned CM follow the instructions here.

    If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

  10. melvin-bot commented on Sep 22, 2026

    @melvin-bot

    ⚠️ Looks like this issue was linked to a Deploy Blocker here

    If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

    If a regression has occurred and you are the assigned CM follow the instructions here.

    If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

  11. Gonals commented on Sep 22, 2026

    @Gonals
    Contributor

    PR Reverted

  12. IuliiaHerets commented on Sep 22, 2026

    @IuliiaHerets

    Chrome / v9.4.91-1
    We see old UI, no issue anymore

    bandicam.2026-09-22.13-27-26-749.mp4
  13. changed the title [-]Expense - Cursor appears briefly on list report field after clicking on it[/-] [+][Due for payment 2026-10-01] Expense - Cursor appears briefly on list report field after clicking on it[/+] on Sep 24, 2026
  14. melvin-bot commented on Sep 24, 2026

    @melvin-bot

    @daledah

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.4.92-8 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-10-01. 🎊

    The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ 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]. If no checklist is needed for this issue, you can click: [no checklist button]

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

Metadata

Metadata

Assignees

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2Engineering

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions