Skip to content

fix(ui,workbench,desktop,webview): swap the thread-title view transition for a header enter animation - #354

Merged
AprilNEA merged 4 commits into
masterfrom
xuan/code-511
Jul 31, 2026
Merged

fix(ui,workbench,desktop,webview): swap the thread-title view transition for a header enter animation#354
AprilNEA merged 4 commits into
masterfrom
xuan/code-511

Conversation

@AprilNEA

Copy link
Copy Markdown
Member

Closes CODE-511. Follow-up to CODE-457 / CODE-469.

Problem

Switching threads animated two titles at once, in opposite directions — the outgoing title flew from the header down into the sidebar while the incoming one flew from the sidebar up to the header. It read as the two labels trading places rather than as one title being promoted.

Root cause

thread-title-${sessionId} was published symmetrically: the sidebar row carried the boundary only while it was not active, and the header carried it keyed by the open session. On a switch A → B that makes two valid pairs in the same transition:

name old new direction
thread-title-A header sidebar row A (boundary re-mounts) header → sidebar
thread-title-B sidebar row B header sidebar → header

enter="none" exit="none" only silences unpaired enter/exit, so both pairs took the default share morph. The direction cannot be suppressed on one side either: commitEnterViewTransitions / commitExitViewTransitions each read props.share from their own boundary, so share="none" on the row makes it skip applying the name to the old snapshot, paired never becomes true, and the wanted direction dies with it.

Same scheme, three more defects:

  • The sidebar snapshot is a narrow truncated bitmap stretched into the ≤420px header slot across a font-normalfont-semibold change — blurry and double-imaged.
  • The two sides render different strings for an unnamed thread: header is active.title ?? tk(active.kind), the row is session.title ?? "<agent> in <repo>".
  • When the outgoing thread's row is not in the DOM (group collapsed, cut by selectVisibleSessions preview truncation) the pair never forms, exit="none" applies, and the old title vanishes instantly — the same interaction animating differently depending on sidebar state.

Fix

Drop matched geometry. The sidebar row goes back to a plain <span>; each header title remounts on sessionId and plays its own enter animation — animate-title-enter, a fade plus a 4px rise on --motion-fast, declared as --animate-title-enter with a nested @keyframes in @linkcode/ui's @theme. A rename inside the open thread keeps the key and stays put.

No <ViewTransition> and no document.startViewTransition survive, so the dead ::view-transition-* rules and the four types: ["react/canary"] entries come out with it (useEffectEvent is in stable index.d.ts; canary was only for ViewTransition).

Verification

Runtime, in the webview mock host (vite --mode mock — 5 seeded threads, no daemon):

  • Three consecutive thread switches: document.startViewTransition called 0 times.
  • A MutationObserver on the header title slot catches the remount each switch; the new node carries animate-title-enter and getAnimations() reports {name: "title-enter", state: "running", duration: 150}.
  • No app element resolves a view-transition-name any more (only the UA's root on <html>), and no view-transition rule survives in the compiled stylesheet.
  • .reduce-motion collapses the duration 0.15s → 1e-05s.

Desktop's MainChromeTitle was not driven in Electron (that needs a built daemon plus a seeded two-session DB). It is covered by typecheck and by its own renderer build output, which emits --animate-title-enter, .animate-title-enter { animation: var(--animate-title-enter) } and @keyframes title-enter with zero view-transition rules — apps/desktop/src/renderer/src/index.css does not import tw-animate-css, so that was the one real compile risk.

pnpm check:ci green. pnpm test: 2151 passed; 2 failures in packages/host/engine/tests/integration/worktree-service.test.ts reproduce with this branch fully stashed, so they predate it and are tracked separately.

@linear-code

linear-code Bot commented Jul 31, 2026

Copy link
Copy Markdown

CODE-511

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 62b00f3af7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/presentation/ui/src/styles.css Outdated
@AprilNEA
AprilNEA merged commit fe034b7 into master Jul 31, 2026
9 checks passed
@AprilNEA
AprilNEA deleted the xuan/code-511 branch July 31, 2026 08:40
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