Commit Graph
4 Commits
Author SHA1 Message Date
peter 7ed98956cc feat(overlay): shared layer-stack for topmost-only Escape across modals, popovers, players (R8 S3)
Replace the three mutually-unaware Escape systems — Modal's private modalStack,
the popovers' document listeners with a blanket stopPropagation, and the two
players' modalCount() checks — with one shared lib/layerStack.ts. Every open
dismissable layer registers in open order; a layer acts on Escape only when it
is topmost, and reads anyLayerAbove() to decide whether to defer. Coordination
is now a stack lookup, not event-propagation order, so it no longer depends on
which listener happens to fire first.

- Modal + useDismiss register via the stack; useDismiss drops the blanket
  stopPropagation (its documented side effect: it swallowed a player's own
  Escape while any popover was open).
- Both players register as a layer and defer via anyLayerAbove() instead of
  modalCount(); PlayerModal checks it before its maximise/fullscreen steps.
  A player MENU is a layer too, so it closes first and the next Escape reaches
  the auto-skip-cancel — fixing the documented PlexPlayer bug.
- AnchoredPopover routes non-hover Escape through the stack (floating-ui's own
  escapeKey off there) and registers as a layer, so a player/modal underneath
  defers once S4 migrates the in-player menus. FloatingTree still owns
  popover-vs-popover ordering; the stack adds the cross-type ordering.
2026-07-30 23:33:50 +02:00
peter 4f7153bb7d fix(toast,overlay): review round 1 — close toast-timer edge, document Escape limit
Review found two low-severity items:
- toast: armDismiss now always clears the prior timer (and arms only when duration is
  truthy), so a coalesced repeat that upgrades a toast to requiresInteraction no longer
  lets the original timer fire and dismiss it. Was a pre-existing gap the C-3.25 change
  hadn't closed.
- overlay: documented the known limitation of useDismiss's blanket stopPropagation — a
  PlexPlayer menu open during an auto-skip countdown swallows the Escape that would also
  cancel the skip. Proper fix needs R8's shared layer-registry (topmost-only dispatch),
  not a broad stopPropagation; accepted until then.
2026-07-21 22:37:42 +02:00
peter 94dfa6a34b fix(player): Escape coordination, focused-Space, light-theme menus (U-C, U-3.1.4, U-3.3.12)
Three player/overlay interaction fixes (PlexPlayer changes share a file, hence one
commit):
- U-C (Escape double-close): useDismiss's Escape now stopPropagation()s (its document
  listener bubbles before a player's window listener, so one Escape closes only the
  popover, not the popover AND the player). Modal exports modalCount(); both players'
  Escape defers when a Modal is open above them, so Escape closes the dialog, not the
  player under it and then the dialog.
- U-3.1.4: PlexPlayer's Space now defers to a focused BUTTON/A (e.g. "Skip intro")
  instead of toggling playback — matching PlayerModal.
- U-3.3.12: the audio/subtitle menus used theme-adaptive glass-menu + forced
  text-white (white-on-white in light theme); they now use the player's own explicit
  dark panel (border-white/15 + bg-neutral-900/95), readable in both themes.
2026-07-21 22:29:40 +02:00
peter a6c2357930 refactor(ui): useDismiss hook for outside-click/Escape close
lib/useDismiss.ts replaces the identical mousedown-outside + Escape effect that
DataTable (filter popover), Channels (tag picker) and AddToPlaylist each hand-rolled.
Positioning stays with each caller (it genuinely varies); AddToPlaylist keeps its
own resize/scroll reposition effect.
2026-06-29 00:11:44 +02:00