fix(style): the hover fade ran at light speed, and stopped dead

Tester feedback via Flo, aimed at the sidebar tabs but true everywhere: 14/s in
means a full fade in seventy milliseconds, which is five frames -- fast enough
to read as a flicker rather than a fade. Halved to 6.5/s in and 4/s out, which
puts the rise around 150ms and the settle around 250ms, where UI fades usually
live.

And the curve was linear: one speed the whole way, then a dead stop. Consumers
now get a smoothstep over the linear state -- soft start, soft landing -- while
the state itself stays linear, because the evict rule and the advance step are
written against it. Every hover in the plugin inherits both changes through the
one Query call, so the sidebar, the popups, the ghost buttons and the message
rows all breathe at the same pace.

The timing test now guards the other direction: it fails if anyone drifts the
rate back toward light speed.
This commit is contained in:
2026-08-19 19:26:47 +02:00
parent 12a445e08f
commit eeffb5bc6b
2 changed files with 18 additions and 5 deletions
+4 -1
View File
@@ -61,7 +61,10 @@ internal static class HoverState
// OR, never assign: a second caller in the same frame that is not hovered
// must not cancel the first one that is.
entry.Hovered |= hovered;
return entry.Value;
// Callers get the eased value; the entry keeps the linear one, which is
// what the evict rule and the advance step are written against.
return HoverMath.Ease(entry.Value);
}
// Never re-entrant: BeginFrame runs once from the draw thread, AdvanceForTest