Skip to content

feat(chat-thread): user-message minimap in place of the jump pill + copy message next to timestamp - #3829

Merged
trunk-io[bot] merged 2 commits into
mainfrom
claude/chat-message-minimap
Jul 27, 2026
Merged

feat(chat-thread): user-message minimap in place of the jump pill + copy message next to timestamp#3829
trunk-io[bot] merged 2 commits into
mainfrom
claude/chat-message-minimap

Conversation

@adamleithp

@adamleithp adamleithp commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

What

Replaces the floating "jump to your message" pill with a minimap of the user's turns, parked at the scroll container's top-right.

2026-07-27 13 44 48 2026-07-27 13 45 21 2026-07-27 13 59 09
  • Collapsed: one 2px tick per user message, width scaled by message length, current turn in accent. Capped at the last 12 ticks so the rail stays small; hidden below 2 user messages.
  • Expanded: hover or keyboard focus opens the full list, anchored to the rail's own top-right corner (sideOffset = -anchor.height) so it expands in place, under the pointer, with no gap to cross. Opens scrolled to the current turn.
  • Rows don't clip with an ellipsis — they fade at the right edge and ticker-scroll to the end on hover/focus (OverflowTickerText, same as sidebar items). Clicking scrolls the thread and leaves the list open for the next hop.
  • Both bodies render it. The windowed body hands it its own onJump and anchorId, since the scroller engine only reaches mounted rows.

Built on quill's DropdownMenu (Base UI), so roving focus, typeahead, Escape and aria-haspopup/expanded come for free. The trigger carries aria-label="Jump to one of your N messages"; ticks are aria-hidden.

Gutter

The rail hugs the scroll container, not the message column, so the thread reserves CHAT_CONTENT_GUTTER on both sides of its scroll content (mirrored, so the column stays centred). Rows clear the rail at any panel width; turn rows drop their extra px now that the gutter provides it.

Removed

ThreadStickyHeader.tsx (both pill variants) and the offscreen flag on the virtualized anchor state, which only existed to time the pill's appearance.

Testing

pnpm --filter @posthog/ui typecheck and the full UI suite (2162 tests) pass. Driven in the running app over CDP: rail renders with the right tick count, hover opens the list, clicking a row scrolls the thread and keeps the list open, Escape closes it, and rows stay clear of the rail down to a 600px-wide panel. The windowed path was exercised by temporarily lowering the virtualization threshold — rail, list and anchor highlight all render there; the jump itself couldn't be observed because that session was mid-stream and auto-follow re-pins the viewport (same for the pill it replaces).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BYPVPkN4Lm3gygchrpcoqr

The floating "jump to your message" pill only ever offered the single
anchored turn, and only once it had scrolled off. Replace it with a
small rail hugging the scroll container's top-right: one tick per user
message, width scaled by message length, current turn highlighted.

Hovering or keyboard-focusing the rail opens the full list, anchored to
the rail's own corner so it expands in place under the pointer. Rows
ticker-scroll their text on hover rather than clipping it, and picking
one scrolls the thread and stays open for the next hop. Built on
quill's DropdownMenu (Base UI), so roving focus, typeahead and Escape
come with it.

Both bodies render it: the windowed body passes its own jump and anchor
(the engine's reach only mounted rows). ThreadStickyHeader and the now
unused `offscreen` anchor flag are deleted.

The thread reserves CHAT_CONTENT_GUTTER on both sides of its scroll
content so rows stay clear of the rail at any panel width, and turn
rows drop their extra px now that the gutter provides it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYPVPkN4Lm3gygchrpcoqr
@trunk-io

trunk-io Bot commented Jul 27, 2026

Copy link
Copy Markdown

😎 Merged successfully - details.

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

React Doctor found 1 issue in 1 file · 1 warning.

1 warning

src/features/sessions/components/chat-thread/MessageMinimap.tsx

Reviewed by React Doctor for commit fa0eafc.

@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "feat(chat-thread): user-message minimap ..." | Re-trigger Greptile

Hover delay 120ms -> 50ms, close delay 80ms -> 30ms. The list opens
over the rail, so there is no pointer travel a long close delay needs
to protect; both linger read as lag.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYPVPkN4Lm3gygchrpcoqr
@adamleithp adamleithp changed the title feat(chat-thread): user-message minimap in place of the jump pill feat(chat-thread): user-message minimap in place of the jump pill + copy message next to timestamp Jul 27, 2026
@adamleithp
adamleithp enabled auto-merge (squash) July 27, 2026 13:33
@trunk-io
trunk-io Bot merged commit bb3f037 into main Jul 27, 2026
33 checks passed
@trunk-io
trunk-io Bot deleted the claude/chat-message-minimap branch July 27, 2026 13:46
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.

2 participants