docs: lock down hover pattern, fix user message bubble flicker

The user message bubble had hover on a `Pressable` wrapping the bubble,
with the timestamp and copy button as siblings outside it — moving the
cursor onto them lost hover. Wrapping both in a single Pressable then
flickered, because `TurnCopyButton` is itself a Pressable and nested
Pressables fight over hover state.

Rewrite `UserMessage` to match the workspace row pattern: hover-tracking
on a plain outer `View` with `onPointerEnter`/`onPointerLeave`, nested
Pressables freely inside. Pointer events are non-bubbling DOM events,
so descendants can't disrupt the outer hover.

Rewrite `docs/hover.md` with the workspace row as THE canonical pattern,
not one option among several. Names the three failure modes that come
from skipping it — including "nested Pressables fight over hover" — and
explicitly bounds when `Pressable.onHoverIn`/`onHoverOut` is acceptable
(self-styling only).

Update `constants/platform.ts` so its hover guidance points at the doc
instead of recommending the broken pattern.
This commit is contained in:
Mohamed Boudra
2026-05-15 11:25:19 +07:00
parent 29d46c5d92
commit 57db997028
4 changed files with 201 additions and 66 deletions
+3 -1
View File
@@ -14,7 +14,9 @@ import { isElectronRuntime, isElectronRuntimeMac } from "@/desktop/host";
// isElectron → Desktop wrapper features (file dialogs, titlebar, updates)
//
// For layout decisions, use useIsCompactFormFactor() from constants/layout.ts.
// For hover, use onHoverIn/onHoverOut on Pressable — no platform gate needed.
// For hover-tracking, see docs/hover.md — the short answer is `onPointerEnter`/
// `onPointerLeave` on a plain `View`, with any press behavior on a separate
// inner `Pressable`. No platform gate needed.
// ---------------------------------------------------------------------------
/** Browser or Electron — the JS runtime has access to the DOM. */