Skip to content

feat(chat): double-click a user message to enter edit mode - #7911

Open
aqiaojoe08 wants to merge 1 commit into
kirodotdev:mainfrom
aqiaojoe08:dblclick-edit-user-message
Open

feat(chat): double-click a user message to enter edit mode#7911
aqiaojoe08 wants to merge 1 commit into
kirodotdev:mainfrom
aqiaojoe08:dblclick-edit-user-message

Conversation

@aqiaojoe08

@aqiaojoe08 aqiaojoe08 commented Sep 2, 2026

Copy link
Copy Markdown

Problem / Motivation

Editing a message you already sent in the chat transcript requires hovering the
message to reveal the action row, then clicking the small pencil icon.
Double-click-to-edit is a widely established convention (Slack, Discord, and the
KiroCrew sidebar's own double-click-to-rename on folders), and its absence on
chat messages is a small but repeated friction when iterating on a prompt.

Why it matters

Iterating on a just-sent prompt is one of the most common chat actions. Requiring
a hover-then-aim-at-a-14px-icon gesture for it is slower and less discoverable
than the double-click users already expect, and inconsistent with the rename
affordance the app ships elsewhere.

What changed (motivation → approach → change)

Goal: let users edit a sent message with the gesture they already expect, without
introducing a second edit path to maintain.

Approach: reuse the existing edit entry point rather than build a new one.
Double-click now calls the same startEdit() the pencil button calls, and is
gated behind the exact same condition that renders the pencil
(canEdit && onEditResend), so it only fires when editing is actually enabled and
there is no divergence between the two triggers.

Change: website/src/pages/chat/UserMessage.tsx adds an onDoubleClick handler on
the read-only message bubble, wired only when canEditResend is true. The handler
(handleDoubleClick) is declared before the editing early-return so React's hook
order stays stable across the read-only and editing renders. A double-click that
lands on a text run still selects a word first (default browser behavior) and only
fires the handler afterward, so it never fights native selection. The bubble stays
a presentational element; the keyboard-accessible path remains the aria-labelled
pencil button, so the mouse-only onDoubleClick carries a scoped
jsx-a11y/no-static-element-interactions disable, matching the pattern already
used for double-click-to-rename in ChatSidebar.tsx.

Tests

website/src/test/UserMessage.test.tsx adds three cases:

  • enters edit mode on double-click of the bubble (textbox appears with the
    original content);
  • does not enter edit mode on double-click when onEditResend is absent;
  • does not enter edit mode on double-click when canEdit is false.

These lock in both the behavior and its gating. Full file: 36/36 pass.

Manual verification

Typecheck (tsc -b), ESLint on the changed files, and the UserMessage vitest
suite all pass locally under Node 24 (the repo's required version). The before/
after render was captured from a faithful standalone harness using the
component's own bubble/edit classes and theme tokens.

Screenshots / video

Double-click on a sent message enters the same edit mode the pencil button opens
(accent-outlined textarea + Cancel/Send):

double-click enters edit mode — before (sent bubble) and after (edit mode)

Related Issues

Fixes #7908

Checklist

  • At most two commits (one is the norm), with a Conventional Commits title (feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)
  • Existing tests pass and new tests added for new functionality
  • Self-review completed; code follows project style guidelines
  • Documentation updated (if applicable) — N/A, no docs affected
  • No secrets, credentials, or internal references in the diff

@aqiaojoe08
aqiaojoe08 requested a review from a team September 2, 2026 16:11
@aqiaojoe08
aqiaojoe08 requested a review from a team as a code owner September 2, 2026 16:11
@aqiaojoe08
aqiaojoe08 requested a review from smeyffret September 2, 2026 16:11
@github-actions github-actions Bot added fork Pull request from a fork (external contributor) readiness: checking Automated validation is still running labels Sep 2, 2026
@aqiaojoe08
aqiaojoe08 force-pushed the dblclick-edit-user-message branch from b5abd0e to c8a58bc Compare September 2, 2026 16:28
@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Sep 2, 2026
@aqiaojoe08

Copy link
Copy Markdown
Author

Check disposition

Dependency Audit / Audit Production Dependencies — accepted-and-deferred.

This failure is not introduced by this PR and is out of its scope. The audit trips on four newly-published high-severity advisories against the transitive fast-uri@3.1.5 in website/electron/package-lock.json (GHSA-5jgf-p345-68v8, GHSA-f65p-4m7j-42xc, GHSA-fph4-wmhf-6fwf, GHSA-jqff-g426-hqxp).

  • This PR touches no dependency manifest — its diff is website/src/pages/chat/UserMessage.tsx, its test, and one screenshot under temp-screenshots/.
  • fast-uri@3.1.5 is present on main independently of this branch, so the audit fails on main and on any PR opened against it today.

Tracked for a maintainer-owned lockfile bump in #7933. The PR Readiness rollup is red only because it aggregates this one pre-existing audit failure; every other completed check is green, including the Focus Cue Gate that the second push fixed.

Fork PR note: the four AI reviews (Design, First Principles, GPT 5.6, Opus 4.8, UX) show SKIPPED — this is the documented fork behavior (secrets are withheld from fork-triggered workflows), not a failure.

@aqiaojoe08
aqiaojoe08 force-pushed the dblclick-edit-user-message branch from c8a58bc to b22bdf4 Compare September 2, 2026 18:31
Double-clicking your own sent message in the chat transcript now enters
edit mode, mirroring the existing pencil button. Gated behind the same
canEdit + onEditResend condition, so it only fires when editing is
enabled and never interferes with native word-selection.

Adds three UserMessage tests covering the new behavior and its gating.
@aqiaojoe08
aqiaojoe08 force-pushed the dblclick-edit-user-message branch from b22bdf4 to 7a75ffd Compare September 2, 2026 18:51
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

First Principles Review (Fable 5, fork) — 🟡 CONCERNS

Premise-level review of 7a75ffd7219c082afcec4f518508fe5ca6607ce4 via the fork AI-review pipeline — why this exists and whether the shipped surface is the smallest honest version. Updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Verification complete. The claimed ChatSidebar precedent for the eslint-disable is real (ChatSidebar.tsx:4674), and the committed screenshot follows the documented temp-screenshots/README.md convention (668 existing files). One undeclared visual change rides along. Final review:

First-Principles-Verdict: CONCERNS

The double-click gesture is grounded in issue #7908 and reuses startEdit, but a focus-within:outline-accent restyle of edit mode rides along undeclared.

What this change ships

Intent: let users open edit mode on a sent chat message with a double-click instead of hover-plus-pencil — an ADDITION.

  1. Double-click a sent message opens the same edit mode as the pencil — justified (issue feat: double-click a user message to enter edit mode #7908; same startEdit, same canEdit && onEditResend gate)
  2. Edit-mode bubble outline brightens from accent/60 to full accent while the textarea is focused — undeclared, rides along
  3. PR screenshot committed under temp-screenshots/dblclick-edit/ — justified (documented convention, temp-screenshots/README.md)
  4. Three tests pinning the gesture and both gating conditions — justified

Watch

  • The focus-within:outline-accent hunk changes the existing pencil-edit visual too, not just the new gesture, and no sentence in the description mentions it ("What changed" names only the onDoubleClick handler). Its zero option costs nobody anything the author has named. Because the textarea is auto-focused on entering edit mode, it near-permanently overrides the accent/60 someone deliberately chose.

Subtractions

  • Drop the focus-within:outline-accent token from the editing bubble's className — it is not part of the stated job; ship it separately with its own rationale if wanted.
  • Delete handleDoubleClick and its hook-order comment; pass startEdit directly (onDoubleClick={canEditResend ? startEdit : undefined}). startEdit is already a useCallback declared before the editing early-return, so the wrapper adds a hook and a comment justifying that hook, and nothing else.

[FIRST-PRINCIPLES-REVIEWED] 7a75ffd

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5, fork) — 🟡 CONCERNS

Design-level review of 7a75ffd7219c082afcec4f518508fe5ca6607ce4 via the fork AI-review pipeline — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Design-Verdict: CONCERNS

Double-click-to-edit hijacks double-click-to-select-word on the one surface where selecting text is an invested-in flow — the description's "never fights native selection" claim is wrong.

Watch

  • The bubble already ships custom select+copy machinery (handleCopy rewrites paste-chip selections), so selecting text from a sent message is a supported flow. The new onDoubleClick={canEditResend ? handleDoubleClick : undefined} fires after the browser selects the word, then startEdit() swaps the bubble for a textarea and destroys that selection — on every editable message, double-click-select-then-copy is now impossible. The description's claim that it "never fights native selection" does not hold: the selection exists for one frame, then the re-render eats it.
  • The cited precedent is weaker than stated: the sidebar analogue is a short non-selectable folder label; Slack and Discord do not edit on message double-click (they select a word). Worth a human judgment call on whether the convention claim justifies overriding the universal gesture.
  • focus-within:outline-accent on the edit container is an unrelated, undocumented styling change smuggled into this PR — trivial, but it belongs in the description or its own commit.

Suggestions

  • Guard the handler: bail out of startEdit() when window.getSelection() is non-collapsed inside the bubble, so a double-click that selected text keeps the selection and only a "dead" double-click edits.

[DESIGN-REVIEWED] 7a75ffd

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

UX Review (Fable 5, fork) — 🟡 CONCERNS

UX-level review of 7a75ffd7219c082afcec4f518508fe5ca6607ce4 via the fork AI-review pipeline — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Context is complete: the diff adds a double-click-to-edit gesture on the sent-message bubble, gated identically to the pencil button, plus tests and a focus-outline polish. Sibling precedents (ChatSidebar rename, FollowUpBar) confirm double-click is an established power gesture here — but those targets are single-line labels/chips, not a body of selectable prose. I've weighed the collision with the universal double-click-to-select-word gesture on message text.

UX-Verdict: CONCERNS

Double-click on message text is the select-a-word gesture; this hijacks it — the selection is destroyed the instant edit mode swaps in the textarea.

Watch

  • Selecting a word to copy from your own message (a path, an ID, a token) now yanks the bubble into edit mode: onDoubleClick={canEditResend ? handleDoubleClick : undefined} fires after the browser's word-select, the re-render replaces the rendered bubble with the textarea (cursor forced to end), and the selection — plus any rendered markdown context — is gone. Frequent gesture × recoverable-but-every-time friction, on the daily transcript surface. Smallest fix: bail in handleDoubleClick when the double-click produced a non-collapsed window.getSelection() inside the bubble, or scope the trigger the way ChatSidebar.tsx:1875 scopes rename to [data-session-title]. Note the sidebar/tab precedents are one-line labels where select-word has no job; a prose bubble is different, and mainstream chat apps leave double-click to selection for exactly this reason.
  • Zero discoverability: nothing reveals the gesture (the sidebar precedent ships title="Double-click to rename"; the bubble carries no hint), so the feature reaches only users who guess. Low impact since the pencil remains — but pair the fix above with appending "(or double-click the message)" to the pencil's edit_resend tooltip.

[UX-REVIEWED] 7a75ffd

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review (fork) — ✅ no blocking findings

Reviewed 7a75ffd7219c082afcec4f518508fe5ca6607ce4 via the fork AI-review pipeline; updated in place on each push.

Review details

No findings.

[OPUS-REVIEWED] 7a75ffd

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review (fork) — ✅ no blocking findings

Reviewed 7a75ffd7219c082afcec4f518508fe5ca6607ce4 via the fork AI-review pipeline; updated in place on each push.

Review details

No findings.
[GPT-REVIEWED] 7a75ffd

@bolichen97

Copy link
Copy Markdown
Collaborator

Open PR relationship audit

This is a consolidated, point-in-time code-level audit note. It compares complete merge-base diffs and current/merged code; it does not treat a shared topic as duplication or partial coverage as completion.

Relationship findings

  • PR #6825 is OVERLAPPING relative to this PR. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #6825: MERGE_DISCUSSION. Independent features on one line; no behavioural contradiction and no goal overlap. Files: website/src/pages/chat/UserMessage.tsx.
  • This PR is OVERLAPPING with PR #7993. The goals differ or the implementations can complement each other; this is not a duplicate claim. Recommended action for PR #7911: CONTINUE_DEVELOPMENT. Merged main does not implement double-click-to-edit at all, so nothing is superseded. It does, however, make the reviewers' selection objection concrete: guard startEdit() on a collapsed window.getSelection() inside the bubble (or scope the trigger away from the prose), so a double-click that selected text keeps that selection. Files: website/src/pages/chat/UserMessage.tsx.

No PR, Issue, label, branch, or review state was changed by the relationship-note portion of this audit.

@github-actions github-actions Bot added the merge conflict Branch has merge conflicts with its base — author must resolve before merge label Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fork Pull request from a fork (external contributor) merge conflict Branch has merge conflicts with its base — author must resolve before merge readiness: action required A blocking check or review needs attention

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: double-click a user message to enter edit mode

2 participants