Files
Nitro-V3/src
simoleo89 4ab38d3f9a toolbar: always-mount nav rows + drive show/hide via framer variants
Replace the outer AnimatePresence wrapper around the four toolbar rows
(desktop backplate, left-nav, right-nav, mobile-nav) with always-mounted
motion.div elements driven by an isVisible-derived variant string
('visible' or 'hidden'). This eliminates the spam-toggle bug: rapid
clicks on the show/hide chevron previously left motion children in
inconsistent intermediate states (stuck opacity 0, phantom scale 0.8)
because AnimatePresence + Fragment + multiple keyed children breaks
when enter/exit cycles overlap. With variants, framer-motion's spring
solver picks up from the current animated value on each retarget, so
spam-clicking just settles smoothly toward whichever target is current.

Refactor details:

- containerVariants drops its 'exit' state (now lives in 'hidden').
- itemVariants drops 'exit' as well — animation target is the same as
  hidden, and exit doesn't apply without AnimatePresence.
- New shellVariants for the backplate.
- pointer-events is animated per-variant ('auto' visible / 'none'
  hidden) instead of pinned via a Tailwind class, so the hidden rows
  don't intercept clicks.
- Wrapper variants are computed inside the component because
  leftNavVariants.hidden depends on isInRoom (the nav slides in from
  the side in-room, from the bottom otherwise).
- Variant inheritance: outer wrapper drives 'visible'/'hidden';
  inner container (containerVariants) and items (itemVariants) inherit
  via framer's variant propagation, so stagger runs in both directions
  without needing AnimatePresence.
- Inner AnimatePresence around the Me popover stays — it has a single
  keyed child with a clean conditional and doesn't suffer from the
  Fragment-wrapping issue.

Cleanups while here:

- Dropped hasDesktopUnifiedShell: always equal to isToolbarOpen inside
  the isInRoom-gated block, so the ternary was always picking one
  branch. Inlined.
- Dropped showDesktopShell: same redundancy inside the (now removed)
  AnimatePresence. The 'else' branch of its ternary was dead code.
- Extracted spring transition constants (SHELL_TRANSITION,
  NAV_TRANSITION, ME_POPOVER_TRANSITION) so they're declared once.
- Removed pointer-events-auto from wrapper className strings where
  the variant now owns it (mobile-nav, left-nav, right-nav).

Behaviour: identical to before for a single click cycle (open → close
animates with the same spring). The previously broken spam-click path
now settles cleanly. Tests still 193/193, typecheck 0 errors, prod
build unchanged.
2026-05-16 12:52:05 +02:00
..
2026-02-19 13:22:37 +01:00
🆙 Init V3
2026-01-31 09:10:52 +01:00