From 86255d269eb750153f0f9d66ed726d6aa23ab263 Mon Sep 17 00:00:00 2001 From: Sundram Gupta Date: Mon, 24 Aug 2026 23:57:58 +0530 Subject: [PATCH] fix(playground): persist bottom sheet collapsed state and expand to stored height --- .../playground/layout-persistence.spec.ts | 47 +++++++++++++++++-- .../docks/BottomSheetDock/BottomSheetDock.tsx | 36 ++++++-------- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts index 5f3e034f..72700fd5 100644 --- a/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts +++ b/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts @@ -80,10 +80,9 @@ test.describe('playground layout persistence (desktop)', () => { await expect(playground.bottomPanel).toBeVisible(); }); - test('a collapsed bottom sheet reopens expanded after a reload', async ({ page, playground }) => { + test('a collapsed bottom sheet stays collapsed after a reload', async ({ page, playground }) => { await playground.open('bottom'); await expect(playground.bottomPanel).toBeVisible(); - const expanded = await playground.bottomPanelHeight(); await playground.grabBottomResizer(); await playground.movePointerToY(890); @@ -92,6 +91,48 @@ test.describe('playground layout persistence (desktop)', () => { await page.reload(); await expect(playground.bottomPanel).toBeVisible(); - expect(Math.abs((await playground.bottomPanelHeight()) - expanded)).toBeLessThan(5); + expect(await playground.bottomPanelHeight()).toBeLessThan(100); + }); + + test('expanding after a collapsed reload restores the pre-collapse height', async ({ page, playground }) => { + await playground.open('bottom'); + await expect(playground.bottomPanel).toBeVisible(); + + await playground.grabBottomResizer(); + await playground.movePointerToY(300); + await playground.releasePointer(); + const resized = await playground.bottomPanelHeight(); + expect(resized).toBeGreaterThan(560); + + await playground.grabBottomResizer(); + await playground.movePointerToY(890); + await playground.releasePointer(); + expect(await playground.bottomPanelHeight()).toBeLessThan(100); + + await page.reload(); + await expect(playground.bottomPanel).toBeVisible(); + expect(await playground.bottomPanelHeight()).toBeLessThan(100); + + await playground.toggleCollapse(); + expect(Math.abs((await playground.bottomPanelHeight()) - resized)).toBeLessThan(5); + }); + + test('Try it after collapsing expands to the persisted height', async ({ requestPage, playground }) => { + await requestPage.open(REQUEST_PATH); + await requestPage.urlBar.tryButton.click(); + await expect(playground.bottomPanel).toBeVisible(); + + await playground.grabBottomResizer(); + await playground.movePointerToY(200); + await playground.releasePointer(); + const resized = await playground.bottomPanelHeight(); + expect(resized).toBeGreaterThan(650); + + await playground.toggleCollapse(); + expect(await playground.bottomPanelHeight()).toBeLessThan(100); + + await requestPage.urlBar.tryButton.click(); + await expect(playground.content).toBeVisible(); + expect(Math.abs((await playground.bottomPanelHeight()) - resized)).toBeLessThan(5); }); }); diff --git a/packages/bruno-api-docs/src/components/Playground/docks/BottomSheetDock/BottomSheetDock.tsx b/packages/bruno-api-docs/src/components/Playground/docks/BottomSheetDock/BottomSheetDock.tsx index 8dc02c3c..da307c9e 100644 --- a/packages/bruno-api-docs/src/components/Playground/docks/BottomSheetDock/BottomSheetDock.tsx +++ b/packages/bruno-api-docs/src/components/Playground/docks/BottomSheetDock/BottomSheetDock.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useRef } from 'react'; import PlaygroundHeader from '../../PlaygroundHeader/PlaygroundHeader'; import { useDockResize } from '@/hooks/useDockResize'; -import { areaFor, readStoredNumber, writeStored } from '@/hooks/useStorage'; +import { areaFor, readStored, readStoredNumber, writeStored } from '@/hooks/useStorage'; import type { DockMode } from '@/utils/playgroundDock'; import { StyledWrapper } from './StyledWrapper'; @@ -9,6 +9,9 @@ const HEADER_HEIGHT = 52; const COLLAPSE_EPSILON = 8; const getDefaultHeight = () => Math.round(window.innerHeight * 0.6); const HEIGHT_STORAGE_KEY = 'oc-docs:playgroundBottomHeight'; +const COLLAPSED_STORAGE_KEY = 'oc-docs:playgroundBottomCollapsed'; + +const readStoredHeight = () => readStoredNumber(areaFor('session'), HEIGHT_STORAGE_KEY, getDefaultHeight()); interface BottomSheetDockProps { dock: DockMode; @@ -29,11 +32,10 @@ const BottomSheetDock: React.FC = ({ openNonce, children }) => { - const defaultHeight = getDefaultHeight(); - const initialHeight = useMemo( - () => readStoredNumber(areaFor('session'), HEIGHT_STORAGE_KEY, getDefaultHeight()), - [] - ); + const initialHeight = useMemo(() => { + const storedCollapsed = readStored(areaFor('session'), COLLAPSED_STORAGE_KEY, false) === true; + return storedCollapsed ? HEADER_HEIGHT : readStoredHeight(); + }, []); const { size, dragging, startDrag, setSize } = useDockResize({ axis: 'y', initial: initialHeight, @@ -41,32 +43,24 @@ const BottomSheetDock: React.FC = ({ max: () => window.innerHeight }); - const lastExpanded = useRef(initialHeight); const collapsed = size <= HEADER_HEIGHT + COLLAPSE_EPSILON; const sizeRef = useRef(size); sizeRef.current = size; - const defaultHeightRef = useRef(defaultHeight); - defaultHeightRef.current = defaultHeight; useEffect(() => { - if (openNonce === undefined) return; - if (sizeRef.current <= HEADER_HEIGHT + COLLAPSE_EPSILON) setSize(defaultHeightRef.current); + if (!openNonce) return; + if (sizeRef.current <= HEADER_HEIGHT + COLLAPSE_EPSILON) setSize(readStoredHeight()); }, [openNonce, setSize]); useEffect(() => { - if (!dragging && size > HEADER_HEIGHT + COLLAPSE_EPSILON) { - writeStored(areaFor('session'), HEIGHT_STORAGE_KEY, size); - } - }, [dragging, size]); + if (dragging) return; + writeStored(areaFor('session'), COLLAPSED_STORAGE_KEY, collapsed); + if (!collapsed) writeStored(areaFor('session'), HEIGHT_STORAGE_KEY, size); + }, [dragging, size, collapsed]); const toggleCollapse = () => { - if (collapsed) { - setSize(lastExpanded.current > HEADER_HEIGHT + COLLAPSE_EPSILON ? lastExpanded.current : defaultHeight); - } else { - lastExpanded.current = size; - setSize(HEADER_HEIGHT); - } + setSize(collapsed ? readStoredHeight() : HEADER_HEIGHT); }; return (