diff --git a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTree.tsx b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTree.tsx index b0c416fc..4c7f3f95 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTree.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTree.tsx @@ -287,6 +287,7 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => { padding: ${spacingsTokens['2xs']}; border-radius: var(--c--globals--spacings--st); width: 100%; + min-width: 200px; background-color: ${rootIsSelected || rootActionsOpen ? 'var(--c--contextuals--background--semantic--contextual--primary)' : 'transparent'}; diff --git a/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx b/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx index 193b0bc8..2922c662 100644 --- a/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx +++ b/src/frontend/apps/impress/src/features/left-panel/components/ResizableLeftPanel.tsx @@ -6,17 +6,15 @@ import { PanelResizeHandle, } from 'react-resizable-panels'; -import { useLeftPanelStore } from '@/features/left-panel/stores'; import { useResponsiveStore } from '@/stores'; +import { useLeftPanelStore } from '../stores'; + // Convert a target pixel width to a percentage of the current viewport width. const pxToPercent = (px: number) => { return (px / window.innerWidth) * 100; }; -const PANEL_TOGGLE_TRANSITION = - 'flex-grow 180ms var(--c--globals--transitions--ease-out), flex-basis 180ms var(--c--globals--transitions--ease-out)'; - type ResizableLeftPanelProps = { leftPanel: React.ReactNode; children: React.ReactNode; @@ -34,70 +32,58 @@ export const ResizableLeftPanel = ({ const { isPanelOpen } = useLeftPanelStore(); const ref = useRef(null); const savedWidthPxRef = useRef(minPanelSizePx); - const previousPanelOpenRef = useRef(isPanelOpen); - const [isToggleAnimating, setIsToggleAnimating] = useState(false); + const [isDragging, setIsDragging] = useState(false); const minPanelSizePercent = pxToPercent(minPanelSizePx); const maxPanelSizePercent = Math.min(pxToPercent(maxPanelSizePx), 40); + + const [panelSizePercent, setPanelSizePercent] = useState(() => { + const initialSize = pxToPercent(minPanelSizePx); + return Math.max( + minPanelSizePercent, + Math.min(initialSize, maxPanelSizePercent), + ); + }); + + /** + * When the panel is toggled open/closed, we want + * to either expand/collapse + */ useEffect(() => { - const syncPanelState = () => { - if (!ref.current || !isDesktop) { - return; - } - - if (!isPanelOpen) { - ref.current.collapse(); - return; - } - - const restoredSizePercent = Math.max( - minPanelSizePercent, - Math.min(pxToPercent(savedWidthPxRef.current), maxPanelSizePercent), - ); - - ref.current.expand(); - ref.current.resize(restoredSizePercent); - }; - - const hasPanelToggleChanged = previousPanelOpenRef.current !== isPanelOpen; - previousPanelOpenRef.current = isPanelOpen; - - if (hasPanelToggleChanged) { - setIsToggleAnimating(true); - const animationFrameId = requestAnimationFrame(() => { - syncPanelState(); - }); - const timeoutId = setTimeout(() => { - setIsToggleAnimating(false); - }, 180); - - return () => { - window.cancelAnimationFrame(animationFrameId); - window.clearTimeout(timeoutId); - }; + if (!ref.current || !isDesktop) { + return; } + if (isPanelOpen) { + ref.current.expand(); + } else { + ref.current.collapse(); + } + }, [isPanelOpen, isDesktop]); - syncPanelState(); - - if (!isDesktop || !isPanelOpen) { + // Keep pixel width constant on window resize + useEffect(() => { + if (!isDesktop) { return; } const handleResize = () => { - syncPanelState(); + const newPercent = pxToPercent(savedWidthPxRef.current); + setPanelSizePercent(newPercent); + if (ref.current) { + ref.current.resize?.(newPercent - (ref.current.getSize() || 0)); + } }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; - }, [isDesktop, isPanelOpen, minPanelSizePercent, maxPanelSizePercent]); + }, [isDesktop]); const handleResize = (sizePercent: number) => { - if (isDesktop && sizePercent > 0) { - const widthPx = (sizePercent / 100) * window.innerWidth; - savedWidthPxRef.current = widthPx; - } + const widthPx = (sizePercent / 100) * window.innerWidth; + savedWidthPxRef.current = widthPx; + setPanelSizePercent(sizePercent); }; return ( @@ -105,21 +91,19 @@ export const ResizableLeftPanel = ({ {leftPanel} - - - - {children} - + {isPanelOpen && ( + + )} + {children} ); };