Skip to content

feat(panel): one annotation card for review threads, in Files changed and the Conversation - #4203

Merged
luke-agent[bot] merged 3 commits into
mainfrom
luke/annotation-card-threads
Oct 20, 2026
Merged

luke-agent[bot] merged 3 commits into
mainfrom
luke/annotation-card-threads

Conversation

@dastratakos

@dastratakos dastratakos commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This is PR 1 of 3 for the approved "Code annotations: one card" design (v3). It moves review threads onto one shared card. PR 2 moves Luke's File-tab notes onto the same card, and PR 3 continues the change band behind it.

  • AnnotationCard (packages/panel/src/tasks/annotation-card.tsx) is the review thread's quiet card: surface ground, quiet border, 10px corners, width capped at min(48rem, 100%).
    • Header: one line that never wraps. It holds the chevron in the file header's 24px slot, the first writer's 20px face, their name (which truncates first), the age, state chips (Resolved, Outdated, Pending), the count, and the ⋯ at the end. The count is a message glyph and a number, shown only while the card is folded. The whole row folds the card, with the disclosure rows' hover fill.
    • No lines in the header, and no preview when folded.
    • One face column and one words column: each reply's face sits under the header's face, and every comment's words sit under the header's name. The positions come from custom properties on .annotation-card that the header and the comments both read, so nothing uses a negative-margin offset.
    • Narrow (container under 440px):
      • the age hides
      • a state becomes a dot, with its word still in the tooltip and the accessible name
      • the count drops its word
      • the card moves to the pane's 8px inset
      • the footer's presses draw closer
  • Conversation cards have a path strip above the header, shown folded or open (the orchestrator's call). It shows the file path cut in the middle so the file name stays, then L12–13, and pressing it goes to the thread in Files changed. The excerpt and comments follow in the body.
  • Files changed cards have no strip, because their place already says which lines. The one exception is a thread above the diff (outdated, or on a line no hunk shows): it has no line to stand on, so its strip carries the lines alone.
  • Kept as before: fold state, deep-link landing (feat(panel): deep links to review threads in the Pull request tab #3884), Reply / Resolve as the card's footer, pending Edit/Delete (feat(service,features,panel): the member's pending review comments on their lines, with Edit and Delete #4015), reactions, ⌘F through folded cards, and the minimized chip (fix(desktop): minimize inline comments to one chip per line, as stage-cli does #3789).
  • Hover: lighting a thread's lines on hover now also works for keyboard focus inside the thread. Like a tooltip, it only does this when the keyboard moved the focus there, so a card that a link lands on and focuses doesn't light lines by itself.

Evidence

Screenshots come from a harness that runs the real AgentPullRequestTab on fixture reads, with the real diff bundle (Pierre plus the highlight worker) and the built styles.css. They show before and after at 900px and 360px, in dark and light, plus hover and folded.

  • pnpm check:affected: panel typecheck ran out of memory (exit 137), so I ran the fallback checks below.
  • tsc --noEmit for packages/panel, apps/desktop and apps/web: clean.
  • ./scripts/oxlint.sh: 0 warnings, 0 errors.
  • biome check: clean on the changed files.
  • pnpm knip: clean.
  • ./scripts/repository-checks.sh: passed.
  • vitest (panel): 280 files. 3 failures in the first run came from swapping in main's sources mid-run for the before shots; the rerun of those files plus the changed ones passed, 349/349.
  • cd apps/desktop && node scripts/build.mjs: bundle budget passes.

New tests in annotation-card.test.ts:

  • Alignment: with the real stylesheet laid, every custom property and sum is resolved, and the test asserts that the header face's x equals the reply faces' x, and the header name's x equals the words' x.
  • No preview when folded: a folded card is its header alone and shows the count; once open, the count goes.
  • Skinny rules: at 360px the age hides, the state is a dot whose word is still in the DOM, and the count drops its word; at 900px they show.

In agent-pull-request-tab.test.ts:

  • Hover lighting: the hover test now also checks that keyboard focus lights a thread's lines and that focus leaving lets them go.
  • Updated selectors: the existing thread tests use the new head, strip and comments selectors, and the strip asserts src/invite.tsL12–13 and src/old.tsL9 (folded).

Test count: +3 tests in a new file.

Screenshots

Before After
Files changed, 900px, dark
Files changed, 900px, light
Files changed, 360px, dark
Files changed, 360px, light
Conversation, 900px, dark
Conversation, 900px, light
Conversation, 360px, dark
Conversation, 360px, light
Hover (lit lines) Folded

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 outside the allowlisted files.
  • No Effect.runPromise/runSync/runFork outside the runtime edges.
  • No new raw async primitives.
  • No dropped Effect statements.
  • Test count: +3 (new annotation-card.test.ts).
  • No hand-rolled file replaced.
  • Doc comments naming the changed parts are edited (agent-pull-request-tab.tsx's header, tasks.css).
  • PRIVACY.md unchanged.
  • Package deps unchanged.
  • Barrel/door rule untouched.

Notes

  • This is desktop/panel only, so no Preview run is needed.
  • Next: PR 2 (Luke's File-tab notes on this card) and PR 3 (the band continued behind the card).

Made with Luke

View guided diff Turn on auto-fix

… and the Conversation

Review threads stand on a shared card (annotation-card.tsx): a one-line
head of chevron, the first writer's face and name, age, states, the count
while folded, and the ⋯; no lines named and nothing previewed while
folded; faces and words each in one column, the head's and every reply's
alike. A narrow card (under 440px) drops the age, draws each state as a
dot that still names it, counts without the word, and keeps to the pane's
inset. A Conversation card, and one above a diff, wear a strip over the
head naming the file and lines. The keyboard in a thread lights its lines
as the pointer does.

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

vercel Bot commented Oct 20, 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 20, 2026 9:12pm UTC

Request Review

luke-agent Bot pushed a commit that referenced this pull request Oct 20, 2026
@luke-agent
luke-agent Bot marked this pull request as ready for review October 20, 2026 21:00
@luke-agent
luke-agent Bot enabled auto-merge October 20, 2026 21:00
Co-authored-by: luke-agent[bot] <339870089+luke-agent[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…us in a chip's thread lights that thread

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 20, 2026
Merged via the queue into main with commit 6416914 Oct 20, 2026
11 checks passed
@luke-agent
luke-agent Bot deleted the luke/annotation-card-threads branch October 20, 2026 21:19

This branch was successfully deployed

1 active deployment
Preview — a4abce28 Deployed Oct 20, 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