Skip to content

feat(panel): select code to comment, keep several line comments open, and light a thread's lines on hover - #3818

Merged
luke-agent[bot] merged 10 commits into
mainfrom
luke/select-to-comment-drafts
Oct 19, 2026
Merged

luke-agent[bot] merged 10 commits into
mainfrom
luke/select-to-comment-drafts

Conversation

@dastratakos

@dastratakos dastratakos commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

C2 of the "Better comment box" stack, after #3792 (C1, merged). It makes three changes to Files changed in the Pull request tab: you can select code to comment on it, keep several line comments open at once, and hover a review thread to light the lines it is on. It is cut from main, so no restack was needed. It includes #3794, #3796, #3798 and #3799.

Summary

  • Select to comment. Select code text in a file and a floating Comment button appears over the selection, as in stage-cli. Pressing it opens the line comment on the lines the selection covers.
    • How lines are read (diff-view/text-selection.ts). Once the drag lets go, the bundle reads the selection from that file's shadow root through Selection.getComposedRanges. It maps each end to its Pierre row (data-line, data-line-type):
      • A removed row counts on the old side and an added row on the new side.
      • An unchanged row counts on its column's side: the left column of a split diff is the old side, and every other column is the new side.
      • A drag that ends at the very start of a row, as a triple-click does, ends on the row before it, even across a gap between hunks.
      • A selection that ends in a note, or crosses into another file, maps to no lines.
    • Where the button shows. The bundle passes the lines and a box around the selected text to the view through a new contract callback, DiffListProps.onSelectText. The view only shows the button where commentLines accepts the range, meaning the hunk lines GitHub takes; expanded context lines get nothing.
    • What dismisses it. A press in the list, a press elsewhere in the window, or a scroll.
    • The button keeps focus where it was, so the selection survives the press.
  • Several drafts (comment-drafts.ts). Line comments are no longer limited to one at a time: several can be open across lines and files.
    • They live above the virtual list, so a comment scrolled out of the window and back keeps its words.
    • Each comment is keyed by its file and range, one per last line and side, as GitHub anchors a thread. Picking lines that end where an open comment ends moves that comment rather than opening a second.
    • Words are kept by file, side and last line, so a comment cancelled unsent comes back with its words when opened there again. A comment GitHub accepted drops its words.
    • The lines of the comment opened or typed in last stay lit.
    • The Minimize inline comments setting keeps a line's threads expanded wherever any comment is being written on that line.
  • New comments get the keyboard. Before this change, the comment's field tried to focus before Pierre had placed its note in the page, so it never got focus. That was invisible with one comment opened from the gutter, but typing after Comment went to the list's keys instead (for example, it folded the file). The field now focuses as soon as its note is in the page.
  • The gutter "+" and lit rows. Both come from Pierre's own defaults, and main shows the same, so style(desktop): Files changed as cards that share one edge, with a quiet fold and a clearer header #3794 didn't cause them.
    • The gutter "+" hung past the line-number column, about a character short of a line's height, and covered the first characters of code. It now stays inside the number column, where it may cover the number.
    • Lit lines also lit the notes under them, so a comment being written sat inside a coloured band. Those notes now keep their own background (LOOK_CSS).
  • Thread hover. Hovering a review thread on its line lights the lines it is on, and so does hovering the chip it's minimized to. The chip lights the widest of its threads' ranges, judged by the order the diff draws its rows. What the pointer rests on is tracked as a stack, so moving from a thread shown under the chip back to the chip lights the chip's lines again. Hover takes priority over a draft's lit lines and gives them back when the pointer leaves.

Desktop and panel only. No change to the service or to what is sent over the wire. Comments still go through memberPullRequestWrite.

Screenshots

Taken from the real AgentPullRequestTab with the real diff bundle and the built styles.css, using synthetic fixtures in headless Chromium driven by Playwright. Every step was a real interaction: a mouse drag to select, a press on Comment, typing, then hovering the thread.

Light Dark
Code selected as text: the floating Comment press
Two comments open at once (lines 10–12, then old line 4, lit as the last opened)
The pointer on Charles's thread lights lines 5–6

Evidence

pnpm check:affected runs out of memory in this sandbox, so I ran the parts one at a time on the merged tree. All passed:

  • tsc for @luke/panel and @luke/desktop
  • ./scripts/oxlint.sh, biome check packages/panel, ./scripts/repository-checks.sh, pnpm knip, node scripts/discarded-effect.mjs
  • vitest for @luke/panel: 198 files, 2,130 tests
  • cd apps/desktop && node scripts/build.mjs, within the bundle budget, which was not re-recorded

Tests (+11)

  • diff-view/text-selection.test.ts (5): only a press on the code starts a drag (a press on a header or a note doesn't, so a selection left behind isn't offered again); a unified selection from a removed row to an added row; an unchanged row in the old column of a split diff; a drag ending at a row's start, across a gap; a selection ending in a note.
  • changes-model.test.ts (1): rowPlace follows the order the diff draws its rows, so an added row drawn before a removed row comes first.
  • agent-pull-request-tab.test.ts (5):
    • Several comments open at once, each with its own words, with the last opened one lit. Cancel closes one. Reopening brings its words back. Lines ending on the same line move the comment.
    • Selected code over hunk lines offers "Comment on lines 12–13", which opens that comment. Lines outside the hunks get no offer, and a released selection removes it.
    • A new comment takes the keyboard once its note is in the page.
    • Hovering a review thread lights its lines, and leaving lets them go.
    • The existing line-comment tests now find comments by their drawn element rather than the single line-comment key.

Invariants

  • ./scripts/check.sh green. (CI)
  • JSON Schema goldens unchanged.
  • Every behavior change has, in this PR, the test that fails without it; no change-detector test added.
  • Gateway envelope goldens unchanged.
  • No new as type assertion.
  • No Effect.runPromise/runSync/runFork outside the runtime edges.
  • No new setTimeout/setInterval/new Promise/AbortController/fs.watch. The bundle waits one requestAnimationFrame after a drag lets go, and the field waits on a MutationObserver, which is disconnected once it fires or on unmount.
  • No Effect, Stream, or Layer written as a statement and dropped.
  • Test count: +11, listed above.
  • Nothing hand-rolled replaced.
  • No AGENTS.md sentence names a changed part.
  • PRIVACY.md unchanged. The Comment button's word is ordinary text that session replay masks, and the tab stays ph-no-capture.
  • Package deps unchanged.
  • Barrel/door rule untouched.

Notes

  • Out of scope, owned by other agents: the file header, the tree, the shortcuts sheet and the diff settings.

Made with Luke

View guided diff Turn on auto-fix

… and light a thread's lines on hover

Files changed offers a floating Comment press over code selected as text
on lines GitHub takes a comment on, read from the file's shadow root once
the drag lets go (diff-view/text-selection.ts), which opens the line
comment on those lines.

Several line comments now stand open at once across lines and files, held
above the virtual list with their words (comment-drafts.ts), keyed by file
and range: one per last line and side, a closed one coming back with its
words, the last opened or written in lit. A new comment takes the keyboard
once the list stands its note in the window.

The pointer resting on a review thread lights the lines it is on.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
@vercel

vercel Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
luke-web Ready Ready Preview Oct 19, 2026 12:02pm UTC

Request Review

luke-agent Bot pushed a commit that referenced this pull request Oct 19, 2026
…lines' rows alone

Pierre hangs the gutter's + past the numbers' column over a line's first characters, and lights the notes under lit lines with them, so a comment being written stood in a coloured band. The + now stands inside the column, and a note under lit lines keeps its own ground.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
@luke-agent
luke-agent Bot force-pushed the luke/select-to-comment-drafts branch from 473c65f to 43df2e8 Compare October 19, 2026 11:15
luke-agent Bot pushed a commit that referenced this pull request Oct 19, 2026
@luke-agent
luke-agent Bot marked this pull request as ready for review October 19, 2026 11:17
@luke-agent
luke-agent Bot enabled auto-merge October 19, 2026 11:17
devin-ai-integration[bot]

This comment was marked as resolved.

@luke-agent
luke-agent Bot disabled auto-merge October 19, 2026 11:19
…ain after a press off the code

The chip a line's threads minimize to lights their lines as each thread
does once shown. A press on a file's header or a note no longer counts as
the start of a drag, so the selection it leaves standing is not read and
offered again as the press lets go.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
@luke-agent
luke-agent Bot enabled auto-merge October 19, 2026 11:26
devin-ai-integration[bot]

This comment was marked as resolved.

…ines again once the pointer leaves a thread it shows

A chip of threads ending on one line lights the widest of their ranges
rather than its first thread's, and what the pointer rests on stands as a
stack, so moving from a thread shown under the chip back onto the chip
lights the chip's lines again.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

… in, by the diff's own row order

The widest of a chip's thread ranges is the one whose first line's row the
diff draws first (`rowPlace`), rather than the old side's before the new,
so an added row drawn before a removed one is never left unlit.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…efore the rows drawn

The threads under one chip all end on a drawn line, so a first line no row
of the patch holds stands before every drawn row, and the chip lights that
thread's range rather than a shorter one.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
… the chip

The setting reaches the list through the app's state a few turns after the press, which a loaded CI worker took longer than one settle for.

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
dastratakos and others added 2 commits October 19, 2026 11:58
…n now names it

Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
@luke-agent
luke-agent Bot added this pull request to the merge queue Oct 19, 2026
Merged via the queue into main with commit f4c7ff4 Oct 19, 2026
11 checks passed
@luke-agent
luke-agent Bot deleted the luke/select-to-comment-drafts branch October 19, 2026 12:11

This branch was successfully deployed

1 active deployment
Preview — 89b756f1 Deployed Oct 19, 2026 by vercel[bot]
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.

1 participant