LearnNewsExamplesServices
Frontmatter
id18117
titleRetargeting a rail reveal to another item of the same rail swaps the pane in one frame: the incoming pane should slide in, and done right the outgoing one cross-fades out
stateClosed
labels
enhancementdesign
assigneesneo-fable
createdAtSep 2, 2026, 5:55 PM
updatedAtSep 2, 2026, 7:03 PM
githubUrlhttps://github.com/neomjs/neo/issues/18117
authorneo-fable
commentsCount0
parentIssue13158
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 2, 2026, 7:03 PM

Retargeting a rail reveal to another item of the same rail swaps the pane in one frame: the incoming pane should slide in, and done right the outgoing one cross-fades out

Closed v13.2.0/archive-v13-2-0-chunk-18 enhancementdesign
neo-fable
neo-fable commented on Sep 2, 2026, 5:55 PM

Sub-issue of #13158 (dock layouts). The operator's exploration request on the Workstation, 2026-09-02 15:50Z, after the exit motion (#18116) landed on the branch: "if we click on one rails item, and then directly (before closing) on a different rails item (same rail) => this could trigger a 'sliding cross-fade'. done right, a lot of eye candy."

What happens today

RevealStateMachine: revealed* + tabClick(other item) → revealed-focused(other) — the reveal retargets, it does not close and reopen. The overlay's afterSetRevealedItem runs syncRevealMotion (no visibility boundary is crossed, so no motion window opens) and syncSnapshot (the title swaps); the rail's pane sync swaps the slot's content (revealOverlay.paneSlot.add(...) from its pane cache). Net effect: the header title and the pane change in one frame while the overlay root stays where it is. Nothing slides, nothing fades.

Two tiers

T1 — the incoming pane slides in from the edge (small, demo-safe). On an item change while visible, re-run the entry keyframes on the header and the pane slot: the root stays (no fade), the new content emerges from under the strip exactly as a fresh reveal does. Mechanism: a CSS animation restarts when its animation-name changes, so the overlay alternates a swap generation class (…-swap-0 / …-swap-1, two identical copies of the per-edge keyframes) on each retarget — no reflow tricks, no timers, the same token duration as the entry. The outgoing pane is under the incoming slide from its first frame (the slot is one element, so the swap itself is instant), which reads as "the new pane slides over the old". The motion window: beginRevealMotion on the swap, settled by the root's end event as today (the root can carry a 0-travel keyframe so its own end fires) or by the slot's end with target identity extended to the slot.

T2 — a true sliding cross-fade (design, post-demo). The outgoing pane stays rendered for one duration, fading and travelling toward the strip while the incoming slides in over it. That needs two layers in the overlay: an outgoing layer that keeps the previous pane mounted (a reparent of a live component — an iframe pane reloads on reparent, a grid does not) or a visual stand-in (a snapshot is not available to the worker). The honest T2 question is which panes may be reparented for a quarter second, and whether the reveal's pane cache (revealPaneCache) already keeps the outgoing instance alive so only its DOM position changes. #13280's motion contract applies: tokens only, neo-dashboard-dock-animating observable, reduced motion collapses through the token.

Acceptance Criteria (T1)

  • AC-1 Component (rail fixture with two items on one rail): reveal item A, click item B's tab; the overlay stays visible throughout (never -hidden, never -leaving), the title reads B, and the header + pane slot carry a running entry animation after the retarget; red on dev (no animation after the retarget).
  • AC-2 Unit (DockRevealOverlay.spec.mjs): an item change while visible flips the swap generation and opens one motion window; an item change while hidden does not.
  • AC-3 The exit (#18116), the entry (#18074) and the existing reveal suites stay green; reduced motion collapses the swap through the token.

Out of Scope (T1)

  • T2's outgoing layer — its own leaf once the reparent question is answered.
  • Retargets across different rails (a new reveal on another edge is a fresh entry already).

Related

#18116 (the exit; T1 stacks on it), #18074 / PR #18079 (the entry), #13280 (the motion contract).

Live latest-open sweep at 2026-09-02T15:53Z: no retarget-motion ticket; A2A: none; Knowledge Base: #13280 and #13158 only.

Authored by Mnemosyne (@neo-fable, Claude Fable 5.1, Claude Code) · session 37bbc610-f0cd-4abb-95c2-eb70336a86f3

tobiu referenced in commit b9232c2 - "feat(dock): a retargeted rail reveal slides its incoming pane in from the edge (#18117) (#18120) on Sep 2, 2026, 7:03 PM
tobiu closed this issue on Sep 2, 2026, 7:03 PM