fix(composer): scope slow reorder pacing to slot travel, not enter/exit

The activity pill slot's single top-level 0.9s transition
(PILL_REORDER_DURATION_S) applied to every animated value, so the
enter/exit fade+scale inherited the slow spring meant only for reorder
travel — pills faded/scaled in and out over 0.9s.

- Split AnimatedPillSlot's transition per value: `layout` keeps the
  0.9s reorder spring unchanged
- `opacity` keeps the 0.9s linear tween only while the slot is moving
  (the mid-move dip keyframes must still land with the layout spring);
  otherwise it uses a fast 0.18s ease-out for enter/exit
- `scale` always uses the fast tween — it only animates on enter/exit
- Add PILL_ENTER_EXIT_DURATION_S (0.18s) alongside the reorder constant

Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
Taylor Ho
2026-08-05 16:42:01 -07:00
committed by Carl
parent 1b3b236555
commit bb1271fcaf
@@ -46,6 +46,12 @@ const TYPING_LABEL_ID = "typing-override";
* keyframes so the fade lands together with the layout switch.
*/
const PILL_REORDER_DURATION_S = 0.9;
/**
* Enter/exit fade+scale for a pill slot. Deliberately much quicker than the
* reorder spring — the slow reorder pacing must not bleed into membership
* changes, which should feel snappy.
*/
const PILL_ENTER_EXIT_DURATION_S = 0.18;
/**
* Strip-level hover popover state: ONE active pill and ONE timer for the
@@ -475,13 +481,31 @@ function AnimatedPillSlot({
shouldReduceMotion
? { duration: 0 }
: {
type: "spring",
duration: PILL_REORDER_DURATION_S,
bounce: 0.15,
opacity: {
type: "tween",
// Only the slot's travel gets the slow reorder pacing; the
// enter/exit fade+scale runs on its own fast tween below.
layout: {
type: "spring",
duration: PILL_REORDER_DURATION_S,
ease: "linear",
bounce: 0.15,
},
// While the slot travels, opacity plays the dip keyframes and
// must land together with the layout spring; otherwise it is
// an enter/exit fade and should be quick.
opacity: isMoving
? {
type: "tween",
duration: PILL_REORDER_DURATION_S,
ease: "linear",
}
: {
type: "tween",
duration: PILL_ENTER_EXIT_DURATION_S,
ease: "easeOut",
},
scale: {
type: "tween",
duration: PILL_ENTER_EXIT_DURATION_S,
ease: "easeOut",
},
}
}