Split out from #36. The other three items shipped in #42; this one was deferred because it's mostly visual-design surface area.
What
When a fit / recenter / zoom-to-node tween completes, the destination node arrives at full opacity at the same time it arrives at full size. The audit's claim: a slight ramp-in of a drop shadow / border accent / glow during the last ~100ms of the tween would draw the eye and reinforce the "you're now focused here" semantics.
Implementation sketch
Two reasonable shapes:
-
Per-node focused state. A focusedNodeId SharedValue + a focusedAccentOpacity derived value. SkiaCardRenderer reads both, fades the accent in when node.id === focusedNodeId.value. Requires plumbing the shared values into every card renderer.
-
One-shot overlay component. A single <FocusIndicator /> that renders a Skia Path / RRect over the focused node's bounds with animated opacity. Lives in SkiaCanvasLayer, reads focusedNodeId + the nodeMap. Less plumbing.
Option 2 is probably the right shape — single component, no per-renderer change, easy to tune visual treatment.
Design call (blocking)
- Drop shadow? Border accent? Glow? Pulse?
- Active for how long after tween completes?
Acceptance criteria
Refs
Split from #36; rest of that issue shipped in #42.
Split out from #36. The other three items shipped in #42; this one was deferred because it's mostly visual-design surface area.
What
When a
fit/recenter/zoom-to-nodetween completes, the destination node arrives at full opacity at the same time it arrives at full size. The audit's claim: a slight ramp-in of a drop shadow / border accent / glow during the last ~100ms of the tween would draw the eye and reinforce the "you're now focused here" semantics.Implementation sketch
Two reasonable shapes:
Per-node focused state. A
focusedNodeIdSharedValue + afocusedAccentOpacityderived value.SkiaCardRendererreads both, fades the accent in whennode.id === focusedNodeId.value. Requires plumbing the shared values into every card renderer.One-shot overlay component. A single
<FocusIndicator />that renders a Skia Path / RRect over the focused node's bounds with animated opacity. Lives inSkiaCanvasLayer, readsfocusedNodeId+ thenodeMap. Less plumbing.Option 2 is probably the right shape — single component, no per-renderer change, easy to tune visual treatment.
Design call (blocking)
Acceptance criteria
fit/recenter/zoom-to-nodecompletionRefs
Split from #36; rest of that issue shipped in #42.