mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
fix(ui): collapse the sidebar atomically, ignoring the lingering hover (PAP-10676)
Clicking the collapse button switched to rail mode but the pointer was still over the panel, so the peek logic immediately re-expanded it — the collapse only "took" once the mouse moved away. Fix in Layout's peek wiring: - Track pointer-over-panel even while expanded (mouse enter/leave handlers are now always wired, but only open a peek when collapsed), so at the moment of collapse we know the pointer is still over the sidebar. - On the expanded→collapsed transition, cancel any pending/active peek (clearPeekTimer + setPeeking(false)) and, when the pointer is still inside, set a suppress flag so the lingering hover can't re-open the peek. The flag is re-armed on the next genuine pointer-leave, so normal hover-to-peek still works afterwards. - Focus-driven peek respects the same suppress flag. Tests: added a Layout test that collapses while hovering and asserts the peek is cancelled and does not re-open, plus a positive-control test proving a normal collapsed-rail hover still opens the peek (so the suppression test is meaningful). 70 sidebar+layout tests pass; tsc clean. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
fc5d173685
commit
05951f20ae
1 file changed
+27
@@ -334,6 +334,33 @@ describe("Layout", () => {
|
||||
await act(async () => { root.unmount(); });
|
||||
});
|
||||
|
||||
it("opens the peek when hovering a collapsed rail (positive control for the hover sim)", async () => {
|
||||
mockSidebarState.collapsed = true;
|
||||
const root = createRoot(container);
|
||||
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Layout />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
});
|
||||
await flushReact();
|
||||
|
||||
const panel = [...container.querySelectorAll<HTMLElement>("div")].find(
|
||||
(el) => el.className.includes("inset-y-0") && el.className.includes("overflow-hidden"),
|
||||
);
|
||||
expect(panel).toBeTruthy();
|
||||
await act(async () => {
|
||||
panel!.dispatchEvent(new MouseEvent("mouseover", { bubbles: true, relatedTarget: document.body }));
|
||||
});
|
||||
await act(async () => { await new Promise((r) => setTimeout(r, 80)); });
|
||||
// A normal collapsed-rail hover (not just-collapsed) opens the peek.
|
||||
expect(mockSetPeeking).toHaveBeenCalledWith(true);
|
||||
|
||||
await act(async () => { root.unmount(); });
|
||||
});
|
||||
|
||||
it("keeps the app sidebar and shows the settings sidebar in the secondary pane on settings routes", async () => {
|
||||
currentPathname = "/PAP/company/settings/access";
|
||||
mockPluginSlots.slots = [
|
||||
|
||||
Reference in new issue
Block a user