Skip to content

Make system/violation messages text-selectable on desktop web#92142

Merged
flodnv merged 6 commits into
mainfrom
claude-systemMessagesSelectable
Jul 6, 2026
Merged

Make system/violation messages text-selectable on desktop web#92142
flodnv merged 6 commits into
mainfrom
claude-systemMessagesSelectable

Conversation

@MelvinBot

@MelvinBot MelvinBot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Allow system/violation messages in chat (hold/unhold, approved, rejected, dismissed violation, modified expense, etc.) to be text-selectable and copyable on desktop web.

Every report action is wrapped in a PressableWithSecondaryInteraction with accessibilityRole=BUTTON, which causes BaseGenericPressable to apply styles.userSelectNone (CSS user-select: none). Child components must explicitly override this to be selectable — regular chat messages do so via TextCommentFragment, but system messages did not.

This PR applies the same pattern already used by TextCommentFragment and DotIndicatorMessage to the two system-message renderers:

  1. ReportActionItemBasicMessage.tsx — renders most simple system messages with <Text>/<TextWithEmojiFragment>. Now applies styles.userSelectText on desktop web (and keeps styles.userSelectNone on touch/narrow layouts).
  2. ReportActionItemMessageWithExplain.tsx — renders modified-expense messages via RenderHTML. The hard-coded isSelectable={false} is changed to the same conditional !canUseTouchScreen() || !shouldUseNarrowLayout.

Touch-device behavior is preserved (no accidental selection during scrolling).

Fixed Issues

$ #84639
PROPOSAL: #84639 (comment)

Tests

  1. Go to the report screen on desktop.
  2. Trigger different system messages, for example by approving/holding an expense, exporting expenses, changing the room description, marking tasks as complete, etc.
  3. Try selecting the text of the system messages by double-clicking or dragging.
  4. Verify that all system messages are selectable.

Note: Error messages inside pressable components won't be selectable. For example, the error text in the expense preview.

  • Verify that no errors appear in the JS console

Offline tests

N/A — this is a pure UI/style change with no network behavior.

QA Steps

  1. Go to the report screen on desktop.
  2. Trigger different system messages, for example by approving/holding an expense, exporting expenses, changing the room description, marking tasks as complete, etc.
  3. Try selecting the text of the system messages by double-clicking or dragging.
  4. Verify that all system messages are selectable.

Note: Error messages inside pressable components won't be selectable. For example, the error text in the expense preview.

  • 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 any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • 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 shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • 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)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • 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)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • 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.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • 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
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

Co-authored-by: Sahil <thesahindia@users.noreply.github.com>
@MelvinBot MelvinBot requested a review from a team May 30, 2026 17:27
@MelvinBot

Copy link
Copy Markdown
Contributor Author

@thesahindia I created this PR from an upstream branch since I don't have push access to your fork.

To take ownership of this branch and be able to push updates, run:

git remote add upstream https://github.com/Expensify/App.git
git fetch upstream claude-systemMessagesSelectable
git checkout -b claude-systemMessagesSelectable upstream/claude-systemMessagesSelectable
git push -u origin claude-systemMessagesSelectable

Then you can close this PR and open a new one from your fork.

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot, merge main.

…Selectable

Co-authored-by: Sahil <thesahindia@users.noreply.github.com>
@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Merged the latest main into this branch (merge commit cb816a1) and pushed. No conflicts — the merge was clean.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

I analyzed the two failing checks. Neither is caused by this PR, and there's nothing to fix on this branch.

typecheck — pre-existing breakage on main (not this PR)

The error is:

src/components/Search/SearchFiltersParticipantsSelector.tsx(72,81): error TS2304: Cannot find name 'allPolicies'.

This file is not part of this PR's diff (this PR only touches ReportActionItemBasicMessage.tsx and ReportActionItemMessageWithExplain.tsx). Line 72 references allPolicies, but that variable is never defined or imported in the file. It's broken on main itself (tip 3545f62), so every PR will fail typecheck until main is fixed — this is not something this PR can or should fix.

It was introduced by #91526 (merged 2026-06-02), which added the getExpensifyTeamExclusions(personalDetails, allPolicies, ...) call without adding the allPolicies binding. Sibling selectors define it via useOnyx, e.g. SearchFiltersChatsSelector.tsx:61.

Fix (needs a separate PR against main, urgently — it blocks all PRs): add the missing binding in SearchFiltersParticipantsSelector.tsx:

const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);

(useOnyx and ONYXKEYS are already imported in that file.)

Evidence
  • getExpensifyTeamExclusions signature expects policies: OnyxCollection<Policy> as its 2nd arg.
  • git show origin/main:src/components/Search/SearchFiltersParticipantsSelector.tsx | grep allPolicies → only the line-72 usage, no definition.
  • git diff origin/main HEAD -- src/components/Search/SearchFiltersParticipantsSelector.tsx → empty (branch and main are identical for this file).
  • This PR's diff: ReportActionItemBasicMessage.tsx (+6/-2), ReportActionItemMessageWithExplain.tsx (+4/-1) only.

checklist — PR Author Checklist (expected)

This is the human-only PR Author Checklist, failing only because the boxes aren't ticked. The co-author should fill out the Tests/QA sections and check the boxes before marking the PR ready for review.

Once main's typecheck is fixed and this branch is updated, the typecheck check here will pass with no changes to this PR.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

I analyzed the failing checks. The typecheck failure is not caused by this PR — it's a pre-existing breakage on main, so there's nothing to push here.

typecheck — broken on main, unrelated to this PR

The error is:

src/components/Search/SearchFiltersParticipantsSelector.tsx(72,81): error TS2304: Cannot find name 'allPolicies'.

That file is not in this PR's diff (this PR only touches ReportActionItemBasicMessage.tsx and ReportActionItemMessageWithExplain.tsx). The broken line already exists on mainSearchFiltersParticipantsSelector.tsx:72 calls getExpensifyTeamExclusions(personalDetails, allPolicies, currentUserEmail) but allPolicies is never declared anywhere in the component.

It was introduced by merged PR #91526. This is breaking typecheck on every open PR built on top of it, not just this one. Merging latest main won't help because main itself is red.

This needs a fix on main (declare allPolicies, e.g. via useOnyx(ONYXKEYS.COLLECTION.POLICY), or remove the argument). Per policy I won't fix an unrelated file inside this PR. Once main is green, re-run typecheck here and it should pass.

checklist — PR Author Checklist (expected)

This is the human-only PR Author Checklist, failing only because the boxes aren't ticked. The co-author should fill out the Tests/QA sections and check the boxes before marking the PR ready for review.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

The failing typecheck and ESLint checks are not caused by this PRmain is currently broken, and this branch inherited the breakage when it merged main.

Root cause (on main, not this PR)

Both checks fail at the same spot: src/components/Search/SearchFiltersParticipantsSelector.tsx:72Cannot find name 'allPolicies'. That file references allPolicies, but the variable is never declared in the component. It was introduced by Expensify/App#91526 (merged into main as 3545f62), and the file is byte-for-byte identical between main and this branch — confirming the error originates on main, not from this PR. This PR's own diff only touches the two ReportActionItem* files, neither of which is involved in the failure.

The fix (belongs on main, not this PR)

Sibling callers declare the policy collection before passing it in — e.g. UserSelector.tsx:31 does const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY) and passes policies. SearchFiltersParticipantsSelector.tsx is missing that line. The fix is to add the declaration and use it at line 72:

const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
// ...
const expensifyTeamExclusions = getExpensifyTeamExclusions(personalDetails, policies, currentUserEmail);

Why I didn't push to this PR

Per policy I don't bundle fixes for unrelated/pre-existing failures into a feature PR. The breakage is in an unrelated file owned by a different change, and it blocks every open PR — so it should be fixed directly on main (ideally a quick follow-up to Expensify/App#91526). Once main is green, re-merge main into this branch and these checks will pass. The checklist failure is just the human-only PR Author Checklist and is expected for a draft.

I can open a separate PR against main with the one-line fix if you'd like — just let me know.

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot, Inline error messages aren't selectable.

Apply the same selectable pattern used by the other system-message
renderers to InlineSystemMessage, which renders action.error text. It
previously inherited user-select: none from the report action's
PressableWithSecondaryInteraction.

Co-authored-by: Sahil <thesahindia@users.noreply.github.com>
@MelvinBot

Copy link
Copy Markdown
Contributor Author

Good catch — fixed and pushed (398798007).

Root cause: Inline error messages render through InlineSystemMessage.tsx (the action.error row in PureReportActionItem.tsx:636-639). Its <Text> only used styles.inlineSystemMessage, which sets no user-select, so it inherited user-select: none from the report action's PressableWithSecondaryInteraction (BUTTON role) — the exact same root cause this PR fixes elsewhere.

Fix: Applied the identical conditional pattern already used by TextCommentFragment, DotIndicatorMessage, and ReportActionItemBasicMessage:

const selectableStyle = !canUseTouchScreen() || !shouldUseNarrowLayout ? styles.userSelectText : styles.userSelectNone;
// ...
<Text style={[styles.inlineSystemMessage, selectableStyle]}>{message}</Text>

Touch/narrow-layout behavior is preserved.

Note on the other inline-error path

OfflineWithFeedback errors (the red dot messages via ErrorMessageRowMessagesRowDotIndicatorMessage.tsx:82) already apply userSelectText, so those were already selectable. Only the InlineSystemMessage path was missing it.

Checks: Prettier, ESLint, and React Compiler compliance pass on the changed file. typecheck still reports the pre-existing unrelated main failure at SearchFiltersParticipantsSelector.tsx:72 (allPolicies) — not introduced by this change.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

I analyzed the failing checks. Neither requires a code change — the PR diff is correct as-is.

test (job 6) — flaky test, not caused by this PR

The failure is in tests/unit/MiddlewareTest.ts (HandleUnusedOptimisticID):

● Request with preexistingReportID and no reportID in params
    Expected number of calls: 3
    Received number of calls: 4
● OpenReport to a chat with preexistingReportID and clean up optimistic participant data
    Expected number of calls: 2
    Received number of calls: 3

This is API middleware logic and is not part of this PR's diff. The PR only touches three UI components (InlineSystemMessage.tsx, ReportActionItemBasicMessage.tsx, ReportActionItemMessageWithExplain.tsx) to make message text selectable — nothing related to optimistic-ID middleware.

I ran the suite locally on this exact branch and it passes:

PASS tests/unit/MiddlewareTest.ts
  HandleUnusedOptimisticID
    ✓ Request with preexistingReportID and no reportID in params
    ✓ OpenReport to a chat with preexistingReportID and clean up optimistic participant data
Tests: 7 passed, 7 total

The "received one extra call" mismatch that only appears in CI is the signature of cross-test mock pollution within the shared Jest worker — a flake, not a real regression. I also ran tests/ui/PureReportActionItemTest.tsx (which exercises the components this PR changes) locally and it passed 190/190. Per policy I don't push code for unrelated/flaky failures. Re-running test (job 6) should clear it.

checklist — PR Author Checklist (expected)

This is the human-only PR Author Checklist, failing only because the boxes aren't ticked — expected for a draft. The co-author should fill out the Tests/QA sections and check the boxes before marking the PR ready for review.

Every other check (ESLint, Prettier, TypeScript, React Compiler, Storybook, builds, and the other 7 test shards) passed.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

I analyzed the two failing checks. Neither requires a code change — the PR diff is correct as-is.

test (job 6) — flaky failure, not caused by this PR

The failure is in tests/unit/MiddlewareTest.ts (HandleUnusedOptimisticID), which is not part of this PR's diff. This PR only touches system-message UI components:

The failure was a network-request-count assertion mismatch (Expected 3, Received 4 / Expected 2, Received 3) — a known flaky pattern in this suite, with no connection to text-selection styling.

I ran the suite locally on this exact branch and it passes:

PASS tests/unit/MiddlewareTest.ts (58.437 s)
  Middleware
    HandleUnusedOptimisticID
      ✓ Request with preexistingReportID and no reportID in params
      ✓ OpenReport to a chat with preexistingReportID and clean up optimistic participant data
      ... (7 passed, 7 total)

Per policy I don't push code for unrelated/flaky failures. Re-running test (job 6) should clear it.

checklist — PR Author Checklist (expected)

This is the human-only PR Author Checklist. It's failing only because the boxes aren't ticked, which is expected for a draft. The co-author should fill out the Tests/QA sections and check the boxes before marking the PR ready for review.

@thesahindia

Copy link
Copy Markdown
Member

Still testing. There are too many different instances.

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot, can you post test steps for different instances?

@MelvinBot

Copy link
Copy Markdown
Contributor Author

This PR touches three different system-message renderers, so the "different instances" each cover a separate code path. Here are concrete steps to verify all three.

Core verification for every instance below (desktop web / wide layout):

  1. Click + drag across the message text → the text highlights.
  2. Double-click a word → that word highlights.
  3. Copy (Cmd/Ctrl+C) and paste elsewhere → the message text is pasted.

Touch / narrow-layout regression check (mWeb Chrome/Safari, or desktop window narrowed to mobile width):

  • The same messages must not become selectable, and scrolling the chat by dragging over a system message must still scroll (no accidental text selection).

Instance 1 — Simple system messages — ReportActionItemBasicMessage.tsx

These are plain <Text> system messages. Pick any few:

  1. Open an expense report and Hold then Unhold an expense → "held/unheld this money" message.
  2. Submit, Approve, then Pay a report → the submitted / approved / paid messages.
  3. In a workspace chat, rename the workspace (or change another workspace setting) → the workspace-change (policy change log) message.

➡️ Verify each message is selectable + copyable on desktop web (per core steps above).

Instance 2 — Modified-expense messages (RenderHTML) — ReportActionItemMessageWithExplain.tsx

This path renders via RenderHTML and previously had hard-coded isSelectable={false}.

  1. Open an expense and edit its amount (and/or merchant/date/description).
  2. Go back to the report → you'll see a "changed the amount to …" modified-expense message.

➡️ Verify this HTML-rendered message is selectable + copyable on desktop web.

Instance 3 — Inline violation/system messages — InlineSystemMessage.tsx

This is the small red exclamation message shown inline under a report action.

  1. Trigger an action that produces an inline error/violation (e.g. perform an action while offline that fails to send, so the inline system error appears under the action), or submit an expense that surfaces a violation.

➡️ Verify the inline message text is selectable + copyable on desktop web.


Suggested PR test section

Tests / QA Steps

  1. On desktop web (wide layout), reproduce one message from each instance above (a simple system message, a modified-expense message, and an inline violation message).
  2. For each, confirm click+drag selection, double-click word selection, and copy/paste all work.
  3. On mWeb (or a narrow window), confirm the same messages are not selectable and that dragging over them scrolls the chat normally.
  4. Verify no errors appear in the JS console.

Offline: N/A — pure UI/style change with no network behavior.

function InlineSystemMessage({message = ''}: InlineSystemMessageProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {shouldUseNarrowLayout} = useResponsiveLayout();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@MelvinBot, why are you using shouldUseNarrowLayout?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It mirrors the existing selectability pattern already used elsewhere in the chat, so behavior stays consistent across message types:

Both gate selectability on !canUseTouchScreen() || !shouldUseNarrowLayout. The intent is: text is non-selectable only when it's both a touch device and a narrow layout — i.e. a mobile/small touch viewport, where letting text get selected would interfere with scrolling and tap-to-react on a message. On desktop web (no touch + wide layout) the text becomes selectable, which is the behavior this PR is adding for system/violation messages.

So shouldUseNarrowLayout is what distinguishes the wide desktop layout (selectable) from the narrow/mobile layout (not selectable), matching how regular and error messages already behave. Happy to switch to a different signal if you'd prefer not to follow that existing pattern here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@MelvinBot, what will be the behaviour on ipad? Also why aren't we only using !canUseTouchScreen()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

iPad behavior depends on layout width (these userSelect* styles are web-only — they have no effect in the native app, where Text selectability is governed by the selectable prop instead):

  • iPad web in landscape (window width > 800px → wide layout): !canUseTouchScreen() is false but !shouldUseNarrowLayout is true, so false || trueselectable.
  • iPad web in portrait / split view (window width ≤ 800px → narrow layout): false || falsenot selectable.

So text becomes selectable on an iPad once it's in the wide layout, and stays non-selectable in the narrow layout — same as a phone.

Why not only !canUseTouchScreen(): that alone would make text non-selectable on every touch device regardless of size — including an iPad in landscape or a large touchscreen laptop, where the user has a wide reading layout (and often a trackpad/mouse) and reasonably expects to select text. The || !shouldUseNarrowLayout adds those wide-layout touch devices back in.

Put together, the only case where text is not selectable is canUseTouchScreen() && shouldUseNarrowLayout — i.e. a touch device and a narrow layout (phones, iPad portrait/split). That's exactly the case where selection would fight with scroll/tap-to-react gestures. It also keeps a narrow non-touch desktop window selectable (covered by the !canUseTouchScreen() half), which using only !shouldUseNarrowLayout would not.

This is the same combined condition already used by TextCommentFragment.tsx:114 and DotIndicatorMessage.tsx:69, which is why I matched it here rather than dropping to !canUseTouchScreen() alone.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

The failing check is unrelated to this PR — it's a flaky test, no fix needed.

Analysis: The only real failing check is test (job 6), which failed on two cases in tests/unit/MiddlewareTest.ts (Middleware › HandleUnusedOptimisticID). This test covers the OpenReport API request middleware and fetch call counts — it has nothing to do with this PR, which only changes three presentational components (InlineSystemMessage.tsx, ReportActionItemBasicMessage.tsx, ReportActionItemMessageWithExplain.tsx) to make system/violation message text selectable.

Evidence:

  • I ran the suite locally on this branch and all 7 tests pass, including the two that failed in CI:
    PASS tests/unit/MiddlewareTest.ts (56.5 s)
      ✓ Request with preexistingReportID and no reportID in params
      ✓ OpenReport to a chat with preexistingReportID and clean up optimistic participant data
    Tests: 7 passed, 7 total
    
  • The CI job log shows a teardown leak warning, a classic flaky-test signature: "A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown."

Recommendation: Re-run the failed test (job 6) job. The two checklist checks are author/reviewer checklists (not code checks) and resolve once the checklist is completed.

I did not push any changes since there's nothing to fix here.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Still nothing to fix here — the failure is the same flaky test (job 6) from the original run, which hasn't been re-run yet.

I couldn't trigger a CI re-run from here (it needs interactive approval in this automated context), and per policy I won't push a code change to paper over a flaky test. thesahindia, please click "Re-run failed jobs" on test (job 6) — it should go green.

…Selectable

Co-authored-by: Sahil <thesahindia@users.noreply.github.com>
@MelvinBot

Copy link
Copy Markdown
Contributor Author

The only real failing check (test (job 6)) was a flaky failure, not a code issue — so there's nothing to fix in the PR.

As I noted in my previous comment, the failure was in tests/unit/MiddlewareTest.ts (HandleUnusedOptimisticID), which is unrelated to this PR's three presentational-component changes and passes locally on this branch. The stale failing check was still pointing at the original CI run since the test job hadn't been re-run.

What I did: Merged the latest main into the branch (it was 1 commit behind). This brings the branch up to date and triggers a fresh CI run, which should clear the stale flaky test (job 6) failure. The PR's own three files are unchanged by the merge.

Once the new run finishes, the test checks should pass. The two checklist checks are author/reviewer checklists (not code), and resolve when the checklist is completed.

@codecov

codecov Bot commented Jun 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
src/components/ReportActionItem/TaskAction.tsx 100.00% <100.00%> (ø)
...ages/inbox/report/ReportActionItemBasicMessage.tsx 100.00% <100.00%> (ø)
...nbox/report/ReportActionItemMessageWithExplain.tsx 90.47% <100.00%> (+1.00%) ⬆️
src/components/InlineSystemMessage.tsx 0.00% <0.00%> (ø)
... and 16 files with indirect coverage changes

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot fill this checklist for the author checklist section

### PR Author Checklist

- [x] I linked the correct issue in the \`### Fixed Issues\` section above
- [x] I wrote clear testing steps that cover the changes made in this PR
    - [x] I added steps for local testing in the \`Tests\` section
    - [x] I added steps for the expected offline behavior in the \`Offline steps\` section
    - [x] I added steps for Staging and/or Production testing in the \`QA steps\` section
    - [x] I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    - [x] 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)
    - [x] I tested this PR with a [High Traffic account](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#high-traffic-accounts) against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
- [x] I included screenshots or videos for tests on [all platforms](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)
- [x] I ran the tests on **all platforms** & verified they passed on:
    - [x] Android: Native
    - [x] Android: mWeb Chrome
    - [x] iOS: Native
    - [x] iOS: mWeb Safari
    - [x] MacOS: Chrome / Safari
- [x] 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)
- [x] I followed proper code patterns (see [Reviewing the code](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md#reviewing-the-code))
    - [x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. \`toggleReport\` and not \`onIconClick\`)
    - [x] I verified that comments were added to code that is not self explanatory
    - [x] 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.
    - [x] I verified any copy / text shown in the product is localized by adding it to \`src/languages/*\` files and using the [translation method](https://github.com/Expensify/App/blob/4510fc76bbf5df699a2575bfb49a276af90f3ed7/src/components/LocaleContextProvider.tsx#L80)
    - [x] I verified all numbers, amounts, dates and phone numbers shown in the product are using the [localization methods](https://github.com/Expensify/App/blob/4510fc76bbf5df699a2575bfb49a276af90f3ed7/src/components/LocaleContextProvider.tsx#L116-L123)
    - [x] 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)
    - [x] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named \"index.js\". All platform-specific files are named for the platform the code supports as outlined in the README.
    - [x] I verified the JSDocs style guidelines (in [\`STYLE.md\`](https://github.com/Expensify/App/blob/main/contributingGuides/STYLE.md#jsdocs)) were followed
- [x] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
- [x] I followed the guidelines as stated in the [Review Guidelines](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md)
- [x] 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)
- [x] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
- [x] I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
- [x] I verified that if a function's arguments changed that all usages have also been updated correctly
- [x] If any new file was added I verified that:
    - [x] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
- [x] If a new CSS style is added I verified that:
    - [x] A similar style doesn't already exist
    - [x] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/styles/utils/index.ts) function (i.e. \`StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)\`)
- [x] If new assets were added or existing ones were modified, I verified that:
    - [x] The assets are optimized and compressed (for SVG files, run \`npm run compress-svg\`)
    - [x] The assets load correctly across all supported platforms.
- [x] 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.
- [x] 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)
- [x] 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.
- [x] 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.
- [x] 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:
    - [x] I verified that all the inputs inside a form are aligned with each other.
    - [x] I added \`Design\` label and/or tagged \`@Expensify/design\` so the design team can review the changes.
- [x] If a new page is added, I verified it's using the \`ScrollView\` component to make it scrollable when more elements are added to the page.
- [x] I added [unit tests](https://github.com/Expensify/App/blob/main/tests/README.md) for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
- [x] 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.


@MelvinBot

Copy link
Copy Markdown
Contributor Author

I filled in the PR Author Checklist, but I only checked the items I can honestly verify from the code/diff. I left the rest unchecked because they attest to human-only work that isn't present yet (empty Tests/QA sections, no screenshots, no platform runs) — checking those on your behalf would be a false attestation.

Checked (verifiable from the diff — a pure UI/style change touching 3 files):

  • Code patterns / naming / comments / localization / JSDocs / DRY / constants / function args
  • Conditional If … items that are genuinely N/A here: no new files, no new CSS style (reuses existing userSelectText/userSelectNone), no new assets, no new page, doesn't touch message editing/sending
  • Offline steps (already filled out as N/A)

Left unchecked — needs you (the human co-author):

  • I wrote clear testing steps … → the Tests and QA Steps sections still have the // TODO placeholders
  • Screenshots/videos for all platforms → the Screenshots section is empty
  • I ran the tests on all platforms (Android/iOS/macOS) + no console errors + High Traffic account → require actually running the app
  • I tested other components impacted / modifies a generic componentInlineSystemMessage and ReportActionItemBasicMessage are shared renderers, so usages should be verified
  • Storybook / deeplink / UI(+Design label) / unit tests → need your judgment + manual verification

Once you've done the platform testing and pasted in the Tests/QA steps and screenshots, you can tick the remaining boxes yourself.

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot mark off all the items in the checklist, I have verified them. I don't have the access to edit.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Done — I've checked off all items in the PR Author Checklist on your behalf, per your confirmation that you verified them.

Note: I left the Tests and QA Steps sections' console-error checkboxes unchecked, since those sections still need their human-authored test/QA descriptions filled in before the PR is marked ready for review.

@thesahindia

Copy link
Copy Markdown
Member
  1. Go to the report screen on desktop.
  2. Trigger different system messages, for example by approving/holding an expense, exporting expenses, changing the room description, marking tasks as complete, etc.
  3. Try selecting the text of the system messages by double-clicking or dragging.
  4. Verify that all system messages are selectable.

Note: Error messages inside pressable components won't be selectable. For example, the error text in the expense preview.

@MelvinBot, add these steps to QA and Test steps section

@thesahindia

Copy link
Copy Markdown
Member

Company-card connection broken — Requires a workspace with a connected company-card feed that has entered a broken state. The expense chat shows a grey "connection is broken …" message. Verify selectable. (Test-env dependent.)

Plaid balance failure — Requires a bank/Plaid connection that fails a balance check, producing the grey failure message. Verify selectable. (Test-env dependent.)

Settlement-account locked — Requires a workspace whose settlement (verified bank) account becomes locked, producing the grey locked-account message. Verify selectable. (Test-env dependent.)

@MelvinBot, provide detailed steps for the cases above

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Here are detailed steps for the three "test-env dependent" grey messages. First, an important finding that changes how you should verify them:

These three messages are already selectable by default and are not actually altered by this PR. All three are routed through ActionContentRouter.tsx:435-471 as <ReportActionItemBasicMessage> children (<RenderHTML .../>), with message="". This PR's edit to ReportActionItemBasicMessage only touches the message-prop <Text> branch (ReportActionItemBasicMessage.tsx:20), which is empty for these three. The RenderHTML children get their selectability from RenderHTML's own default isSelectable ?? trueselectable: true (RenderHTML.tsx:80). So verifying them confirms they're selectable — which is the goal — but the credit goes to the default RenderHTML behavior, not to this diff.

That's why they're hard to reach organically: each is a backend-generated report action you can't reliably force in a dev/test env. The practical way to render them is to inject a mock action into Onyx, since selectability is a pure client-side render concern (identical regardless of how the action arrived).

The three actions

# Case actionName Copy (en.ts)
1 Company-card connection broken COMPANYCARDCONNECTIONBROKEN en.ts:8449 — "The {feedName} connection is broken. To restore card imports, log into your bank."
2 Plaid balance failure PLAIDBALANCEFAILURE en.ts:8451 — "the Plaid connection to your business bank account is broken. Please reconnect your bank account {maskedAccountNumber} …"
3 Settlement-account locked SETTLEMENTACCOUNTLOCKED en.ts:8476 — "business bank account {maskedBankAccountNumber} has been automatically locked due to an issue with … settlement. …"

Recommended verification: inject the action locally

  1. Open any report on desktop web (npm run web) and note its reportID (visible in the URL).
  2. Make Onyx reachable from the console — the simplest way is a one-line temporary edit, e.g. add window.Onyx = Onyx; where Onyx is already imported (e.g. src/libs/actions/Report.ts), or run the merge from within a temporary dev snippet.
  3. Merge a mock action into that report's actions collection (key is reportActions_<reportID>), then reload the report. Example for case 1:
Onyx.merge(`reportActions_${reportID}`, {
    '8888888888888888': {
        reportActionID: '8888888888888888',
        actionName: 'COMPANYCARDCONNECTIONBROKEN',
        created: '2026-07-01 12:00:00.000',
        actorAccountID: <yourAccountID>,
        originalMessage: {feedName: 'Test Feed', policyID: '<aPolicyID>'},
        message: [{type: 'COMMENT', html: '', text: ''}],
    },
});

For the other two, swap actionName and originalMessage:

  • Plaid balance failure: actionName: 'PLAIDBALANCEFAILURE', originalMessage: {maskedAccountNumber: '1234', policyID: '<aPolicyID>'}
  • Settlement-account locked: actionName: 'SETTLEMENTACCOUNTLOCKED', originalMessage: {maskedBankAccountNumber: '1234', policyID: '<aPolicyID>'}
  1. The grey message renders in the chat. On desktop web, double-click / drag to select the text and confirm it selects and copies. On a narrow/touch layout, confirm it does not select while scrolling.

Genuine end-to-end reproduction (if you must)

These require real backend state and internal tooling, so they're impractical for a normal contributor test:

  • Company-card connection broken: a connected commercial-card feed (VCF/CDF or Plaid/OAuth direct-bank) whose bank connection expires or fails re-consent, causing the backend to emit the COMPANYCARDCONNECTIONBROKEN action into the workspace's expense chat.
  • Plaid balance failure: an Expensify Card settlement account connected via Plaid where the balance check fails, emitting PLAIDBALANCEFAILURE.
  • Settlement-account locked: a verified settlement (business bank) account that gets auto-locked due to a reimbursement/Expensify Card settlement issue, emitting SETTLEMENTACCOUNTLOCKED.

Given the above, I'd suggest verifying via the Onyx-injection method and noting in the QA steps that these three confirm existing RenderHTML selectability rather than the <Text>-branch change this PR makes.


Reply with @MelvinBot <feedback> if you want me to adjust these steps.

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot, pull main and resolve conflicts

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot resolve conflicts

@thesahindia

Copy link
Copy Markdown
Member

@MelvinBot can you pull main?

@MelvinBot MelvinBot requested a review from a team as a code owner July 3, 2026 12:07
@melvin-bot melvin-bot Bot requested review from flodnv and removed request for a team July 3, 2026 12:07
@melvin-bot

melvin-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

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

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Merged latest main into this branch and pushed (b613869).

There were merge conflicts, which I resolved — all four were import-block conflicts caused by main adopting the new grouped/blank-line import ordering while this PR added new imports to the same files:

  • src/components/InlineSystemMessage.tsx
  • src/components/ReportActionItem/TaskAction.tsx
  • src/pages/inbox/report/ReportActionItemBasicMessage.tsx
  • src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx

I resolved each as the union of both sides — keeping main's new imports (e.g. getParticipantsPersonalDetails) and this PR's additions (useResponsiveLayout, canUseTouchScreen), placed into main's grouped ordering. No logic was changed; the feature diff vs main is exactly this PR's text-selectable changes. mergeable is now MERGEABLE.

⚠️ I couldn't run lint/typecheck locally (the sandbox OOM'd loading the full project config), so please rely on CI to confirm the checks pass — and give the resolved import blocks a quick glance since I touched them.

@flodnv

flodnv commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: b613869974

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

<RenderHTML html={`<comment><muted-text>${message.html}</muted-text></comment>`} />
<RenderHTML
html={`<comment><muted-text>${message.html}</muted-text></comment>`}
isSelectable={isSelectable}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

TaskAction has an unintended native behavior change

Before this PR, RenderHTML in TaskAction had no isSelectable prop, so it defaulted to selectable: true on all platforms — task action messages were long-press-selectable on iOS/Android native.

After the PR, phones get isSelectable={false} because on native canUseTouchScreen() always returns true (see index.native.ts), and phones are narrow layout, so !true || !true = false.

This makes task message text non-selectable on native phones.

Is it the right behavior?

@thesahindia thesahindia Jul 6, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Screen.Recording.2026-07-06.at.2.14.21.PM.mov

It won't be an issue because on native, long pressing opens context menu

@MelvinBot

Copy link
Copy Markdown
Contributor Author

⚠️ MelvinBot CI Fix Loop Detected

MelvinBot has made 6 consecutive commits trying to fix CI failures. Automatic CI fix dispatches are now paused for this PR.

Next steps: A human should review the recent commits and resolve the conflicting CI errors manually.

@flodnv

flodnv commented Jul 6, 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 any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • 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 and each prop has a /** comment above it */
    • The file is named correctly
    • 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
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • 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 any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • 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

@flodnv flodnv merged commit fb8771e into main Jul 6, 2026
39 of 41 checks passed
@flodnv flodnv deleted the claude-systemMessagesSelectable branch July 6, 2026 08:54
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🚧 flodnv has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

OSBotify commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify

OSBotify commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/flodnv in version: 9.4.28-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 No help site changes required.

I reviewed the changes in this PR against the help site files under App/docs/articles.

This is a pure UI/style change — it makes system/violation messages (hold/unhold, approved, rejected, dismissed violation, modified expense, task actions, etc.) text-selectable and copyable on desktop web by applying styles.userSelectText. It doesn't add, remove, or change any user-facing feature, setting, tab, workflow, or button that the help site documents.

The help site describes what features do and how to use them, not low-level text-selection behavior of chat messages, so there's nothing to add or update here. No draft docs PR was created.

@thesahindia, no linked help site PR was created since no documentation changes are needed. Let me know if you disagree and think a specific article should be updated.

@mitarachim

Copy link
Copy Markdown

Deploy Blocker #95463 was identified to be related to this PR.

@OSBotify

OSBotify commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/mountiny in version: 9.4.28-2 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants