Repository navigation
fix(channels): close the activity popover through Base UI actions - #891
Conversation
wesbillman
left a comment
There was a problem hiding this comment.
No changes requested. The four app-initiated close paths now use Base UI’s action API, which dispatches the hover-cleanup event while preserving the existing navigation callbacks and controlled state.
Star Lord’s automated source review via Wes’s account — head a4e144cbd2db5f04def5200d56e1d8059714b7cb, base ecfbb8a5835dd0fb04e48111ef406a975f2c7715. Source-only: no tests or app execution; the one-time CI snapshot shows required checks passing (Windows native validation skipped), but live keyboard/pointer behavior and human acceptance remain unverified.
972da32 to
370c56d
Compare
Closing ChannelActivityPopover by flipping the controlled `open` prop (`setOpen(false)`) never emits a Base UI `openchange` event, so the hover interaction installed by `openOnHover` is not cleaned up: the safePolygon document `mousemove` handler, the stale `openEvent`, and the 150 ms close timer all outlive the close. On WebKit the handler stays armed until the next real pointer move, then schedules a `trigger-hover` close that lands inside the keyboard-reopened popup and drops focus to `body` (me-workspace.spec.mjs "Me sidebar shares working activity", flaky in CI and 3/15 locally). Chromium is saved only by a synthesized `mouseleave` on unmount. Route every app-initiated close through `actionsRef.current.close()`, as TypingIndicator already does, so Base UI dispatches `openchange` and tears down the hover state. The `hasActivity` effect additionally guards on `open` to avoid imperative closes on already-closed instances. Verified: `tsc --noEmit` clean; ChannelActivityPopover vitest 4/4; me-workspace.spec.mjs x15 passes 15/15 on WebKit (was 3/15 failing) and 15/15 on Chromium. Co-Authored-By: Claude Fable 5.1 <[email protected]> Signed-off-by: Matt Toohey <[email protected]> Signed-off-by: cid <d9f92a72922bf45c17379a47d64dae84b6020397c2d5a52b5317d512068cd9d3@buzz.block.builderlab.xyz>
370c56d to
3f57cb3
Compare
wesbillman
left a comment
There was a problem hiding this comment.
No changes requested in this integration follow-up. The remaining activity-disappearance close uses Base UI’s action API and remains compatible with the newer keyboard/touch hover-dismissal guard; failed mark-read attempts retain the existing retry path.
Star Lord’s automated source review via Wes’s account — head 3f57cb357964e7a36f5f7305f1ec66f6cdb2d760, base 0ec0c1adbdceb480e49f218e261d9c38d44d2a3c. Source-only, including public PR material; no tests or app execution. The CI snapshot still had one WebKit shard running and Windows skipped; live keyboard/pointer and human/native acceptance remain unverified.
* commit 'ad4040dee': Port IFC policy library and session APIs (#835) Give Codex the Buzz base prompt (#984) refactor(channels): remove personal groups (#988) Replace the agent icon with the Soft & wide mark (#932) fix(channels): close the activity popover through Base UI actions (#891) Restore model and effort picks when a background send is recovered (#887) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
* origin/main: (22 commits) Polish workspace surfaces, split controls, and emoji composition (#801) fix: wake reading after an exact message reveal (#1006) feat(pairing): copy the pairing code from Settings (#1003) Ignore .scratch in the Vite dev watcher (#1001) fix(client): recover websocket connections across repeated rollouts (#996) test: fix six cross-branch CI flakes (#1002) feat(agents): run Buzz's own copies of Claude and Codex, kept on the latest release (#949) ci: repeat changed Vitest and Playwright tests 10x on pull requests (#890) feat(agents): restore agent memory (#982) Soften compact dropdown outlines (#991) fix(agents): manage providers, models, and agent migrations (#952) Port IFC policy library and session APIs (#835) Give Codex the Buzz base prompt (#984) refactor(channels): remove personal groups (#988) Replace the agent icon with the Soft & wide mark (#932) fix(channels): close the activity popover through Base UI actions (#891) Restore model and effort picks when a background send is recovered (#887) test(navigation): isolate the keyboard retry session gate (#981) fix(codex): log failed idle terminal clean instead of swallowing it (#878) feat(agents2): set the clicked conversation's session apart in agent tabs (#846) ... Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>
Summary
Fixes the flaky
me-workspace.spec.mjs"Me sidebar shares working activity" browser journey (WebKit).ChannelActivityPopoverclosed itself by flipping its controlledopenprop (setOpen(false)). That never emits a Base UIopenchangeevent, so the hover interaction installed byopenOnHoverwas never cleaned up. The safePolygon documentmousemovehandler, the staleopenEvent, and the 150 ms close timer all stayed alive after the close. On WebKit the handler stayed armed until the next real pointer move. It then scheduled atrigger-hoverclose that landed inside the popup after the keyboard reopened it, and focus dropped tobody. Chromium only avoided this because unmounting synthesizes amouseleave.This is a product defect in the popover's close path, not a test-timing problem, so the fix lives in the component and the spec is unchanged.
Changes
actionsRef.current.close(), the same wayTypingIndicatoralready does. Base UI then dispatchesopenchangeand tears down its hover state.hasActivityeffect also checksopen, so it doesn't call an imperative close on a popover that's already closed.Validation
All of this was run locally on macOS and covers only what's listed:
tsc --noEmit: cleanChannelActivityPopovervitest: 4/4 passme-workspace.spec.mjsrepeated 15 times: WebKit 15/15 pass (before the fix, 3 of 15 runs failed); Chromium 15/15 passDeferred:
A green run doesn't prove every flake in this spec is gone.
🤖 Generated with Claude Code