Skip to content

fix(session-ui): polish compaction divider hover, sticky summary header and long tool rows - #59330

Open
kitlangton wants to merge 6 commits into
devfrom
compaction-polish
Open

kitlangton wants to merge 6 commits into
devfrom
compaction-polish

Conversation

@kitlangton

@kitlangton kitlangton commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

The "Compacted" divider now warms as one word on hover, stays reachable while its summary is open, and long tool rows fade out instead of cutting off.
Compaction is when the app folds old conversation into a short summary; the "Compacted" divider opens it. Short tool rows and closed summaries look the same as before.

❌ Before

  1. Hovering "Compacted" warmed only the "acted" ending, splitting the word in two.
  2. Scrolling deep into an open summary left the divider far above, so collapsing meant scrolling back up. An open summary also closed itself when its row scrolled out of the timeline and back, or after switching tabs.
  3. A long shell command or file list in a tool row was cut off hard at the row's edge.

✅ After

  1. The whole word warms on hover.
  2. While a summary is open, its divider sticks to the top of the timeline like an open tool group's header. Text scrolling under it, or under a stuck tool group header, fades out over 28px on an eased curve instead of being sliced along the header's edge, and the fade eases in over 240ms as the header sticks. Collapsing it scrolls back first, so the divider stays where you clicked, even when the timeline was following the end. The summary stays open when its row scrolls away and back.
  3. A row that is too long fades out over its last 32px on the same eased curve. Rows that fit keep their last letters. The fade flips side in right-to-left layouts.
- .session-compaction-done:hover { color: muted }
+ .session-compaction-label:hover { color: muted }
+ [data-open] .session-compaction-header { position: sticky; top: var(--sticky-accordion-top) }
+ stuck header::after { 28px bg, eased 8-stop mask, opacity 240ms, pointer-events: none }   // @container scroll-state(stuck: top), compaction + tool groups
- .tool-subtitle { text-overflow: ellipsis }
+ .tool-subtitle { 32px eased 8-stop mask fade, driven by scroll(self inline) }
- .exa-tool-query { text-overflow: ellipsis }   // re-added "…" inside the fade

  QuietCompaction
-   open = createSignal(false)                   // lost when the virtualizer unmounts the row
+   open = disclosure[message.id]                // like shell messages
    collapse from stuck header:
+     unpin()                                    // virtualizer.onUnpin, or resize snaps back to the end
      scrollBy(-stuck)

📊 Proof

Fades zoomed at 2x: the previous linear ramps (16px under stuck headers, 24px on rows) left a visible band; the eased ramps don't.

Linear (previous head) Eased
Stuck compaction header
Stuck tool group header
Long shell row

Against dev (the After shots here predate the eased fades):

Before After
Hover
Scrolled into an open summary
Scrolled into an open tool group (hard cut)
Long shell rows

Right-to-left rows:

Sticky collapse clip: https://problems.kitlangton.com/media/5YbxoGAnpJKcHyfT66D-CA.mp4

Three new component tests (sticky header collapses in place and shows its fade only while stuck; overflowing row fades, short one doesn't; long web search query fades with no ellipsis) fail without the change and pass here. Keeping the summary open across remounts and the unpin have no automated test: both need the app's virtualized timeline with real compaction rows.

👀 Read: the stuck-header fade uses scroll-state container queries; without them a header just keeps today's hard edge. When a file card sticks right under an open tool group header, the fade also softens that card's top border. basic-tool.css, the row fade. It relies on scroll-driven animation, so a browser without it shows plain clipped text with no ellipsis; Electron and current Chromium have it. Shell commands stay left-to-right, so their fade stays on the right even in an RTL layout. The rest is routine.

Found while using the session timeline · screenshots from the component stories · zoomed fade stills taken on the current head

Checks run
  • bun typecheck in packages/session-ui: no errors; bun run lint:changed: clean
  • Component specs for compaction, tool groups, sticky, basic tool and read group on the current head: 32/32 pass
  • Component specs for compaction, tool groups, sticky, basic tool, shell, read group and disclosure: 42/42 pass
  • App component specs for the timeline virtualizer, timeline detail and web search: 25/25 pass

@kitlangton kitlangton changed the title fix(session-ui): polish compaction divider hover, sticky summary header and tool row fade fix(app): polish compaction divider hover, sticky summary header and long tool rows Oct 26, 2026
@kitlangton kitlangton changed the title fix(app): polish compaction divider hover, sticky summary header and long tool rows fix(session-ui): polish compaction divider hover, sticky summary header and long tool rows Oct 26, 2026
@kitlangton
kitlangton changed the base branch from dev to beta October 26, 2026 20:04
@thdxr
thdxr changed the base branch from beta to dev October 27, 2026 16:38

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant