fix: discard pending sidebar width on collapse
This commit is contained in:
parent
a19dbda2a2
commit
5adfbed97d
|
|
@ -511,4 +511,37 @@ describe("Sidebar", () => {
|
|||
expect(document.documentElement.style.getPropertyValue("--ao-sidebar-w")).toBe("280px");
|
||||
expect(window.localStorage.getItem("ao-sidebar-w")).toBe("280");
|
||||
});
|
||||
|
||||
it("discards a queued narrow resize frame when collapsing", async () => {
|
||||
let queuedFrame: FrameRequestCallback | undefined;
|
||||
const requestAnimationFrameSpy = vi.spyOn(window, "requestAnimationFrame").mockImplementation((callback) => {
|
||||
queuedFrame = callback;
|
||||
return 1;
|
||||
});
|
||||
const cancelAnimationFrameSpy = vi.spyOn(window, "cancelAnimationFrame").mockImplementation(() => undefined);
|
||||
|
||||
try {
|
||||
renderSidebar();
|
||||
|
||||
const resizeHandle = document.querySelector(".resize-handle--right");
|
||||
if (!(resizeHandle instanceof HTMLElement)) throw new Error("Resize handle not found");
|
||||
|
||||
fireEvent.pointerDown(resizeHandle, { clientX: 240 });
|
||||
fireEvent.pointerMove(window, { clientX: 205 });
|
||||
fireEvent.pointerMove(window, { clientX: 120 });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(document.querySelector('[data-slot="sidebar"][data-state="collapsed"]')).toBeInTheDocument();
|
||||
});
|
||||
expect(cancelAnimationFrameSpy).toHaveBeenCalledWith(1);
|
||||
expect(window.localStorage.getItem("ao-sidebar-w")).toBe("240");
|
||||
expect(document.documentElement.style.getPropertyValue("--ao-sidebar-w")).toBe("240px");
|
||||
|
||||
queuedFrame?.(performance.now());
|
||||
expect(document.documentElement.style.getPropertyValue("--ao-sidebar-w")).toBe("240px");
|
||||
} finally {
|
||||
requestAnimationFrameSpy.mockRestore();
|
||||
cancelAnimationFrameSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -79,6 +79,14 @@ export function useResizable({
|
|||
if (pending !== null) apply(pending);
|
||||
}, [apply]);
|
||||
|
||||
const discardPending = useCallback(() => {
|
||||
if (frameRef.current !== null) {
|
||||
window.cancelAnimationFrame(frameRef.current);
|
||||
frameRef.current = null;
|
||||
}
|
||||
pendingWidthRef.current = null;
|
||||
}, []);
|
||||
|
||||
// Restore persisted width on mount.
|
||||
useEffect(() => {
|
||||
const saved = Number(window.localStorage.getItem(storageKey));
|
||||
|
|
@ -109,8 +117,10 @@ export function useResizable({
|
|||
const nextWidth = startWidth + sign * (e.clientX - startX);
|
||||
if (collapseBelow !== undefined && onCollapse && nextWidth <= collapseBelow) {
|
||||
collapsed = true;
|
||||
flushPending();
|
||||
window.localStorage.setItem(storageKey, String(Math.min(max, Math.max(min, startWidth))));
|
||||
const preservedWidth = Math.min(max, Math.max(min, startWidth));
|
||||
discardPending();
|
||||
apply(preservedWidth);
|
||||
window.localStorage.setItem(storageKey, String(preservedWidth));
|
||||
onUp();
|
||||
onCollapse();
|
||||
return;
|
||||
|
|
@ -120,7 +130,7 @@ export function useResizable({
|
|||
window.addEventListener("pointermove", onMove);
|
||||
window.addEventListener("pointerup", onUp);
|
||||
},
|
||||
[applyOnFrame, collapseBelow, edge, flushPending, max, min, onCollapse, storageKey],
|
||||
[apply, applyOnFrame, collapseBelow, discardPending, edge, flushPending, max, min, onCollapse, storageKey],
|
||||
);
|
||||
|
||||
const onCollapsedPointerDown = useCallback(
|
||||
|
|
|
|||
Loading…
Reference in New Issue