Reputation: 1
I'm experiencing an unexpected behaviour with the SplitPane component from the "split-pane-react" package (version 0.1.3) in my React project. The issue occurs when the SplitPane is scaled down using Framer Motion and the browser window is resized.
Environment:
React: ^18.2.0 Framer Motion: ^11.2.4 split-pane-react: 0.1.3
Description of the problem:
Initially, the SplitPane renders correctly with two panes. When toggled on, the SplitPane is translated and scaled down to roughly 1/5th of its original size using Framer Motion. After this translation, if the browser window size is changed, the contents of the SplitPane experience a dramatic reduction in width. The issue can be temporarily fixed by toggling the translation off and changing the window size again. This behavior persists regardless of the content in the panes. No errors are printed to the console during this process.
Expected behavior: The SplitPane should maintain its relative proportions and content sizes even when scaled down and the window is resized.
const [sizes, setSizes] = useState<number[]>([50, 50]);
const containerRef = useRef<HTMLDivElement>(null);
const [containerWidth, setContainerWidth] = useState<number>(0);
const [shrink, setShrink] = useState(false);
const [scaleFactor, setScaleFactor] = useState(1);
const [scaledRightOffset, setScaledRightOffset] = useState(0);
const [scaledTopOffset, setScaledTopOffset] = useState(0);
// To recalculate position on screen of translated SplitPane
useLayoutEffect(() => {
const handleResize = () => {
const targetWidth = 180;
const originalWidth = document.body.clientWidth - 96; // 96 is x padding
const widthScale = targetWidth / originalWidth;
const targetHeight = 111;
const originalHeight = document.body.clientHeight - 155; // 155 is top offset
const heightScale = targetHeight / originalHeight;
const rightOffset = (targetWidth - (originalWidth * heightScale)) / 2;
const topOffset = (targetHeight - (originalHeight * widthScale)) / 2;
if (widthScale < heightScale) {
setScaleFactor(widthScale);
setScaledTopOffset(topOffset);
setScaledRightOffset(0);
} else {
setScaleFactor(heightScale);
setScaledTopOffset(0);
setScaledRightOffset(rightOffset);
}
}
handleResize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
useEffect(() => {
const updateContainerWidth = () => {
if (containerRef.current instanceof HTMLElement) {
const newWidth = containerRef.current.offsetWidth;
setContainerWidth(newWidth);
}
};
updateContainerWidth();
window.addEventListener('resize', updateContainerWidth);
return () => window.removeEventListener('resize', updateContainerWidth);
}, []);
useEffect(() => {
if (shrink || hide) {
// When shrinking or hiding, store current sizes as percentages
setSizes(prevSizes => prevSizes.map(size => (size / containerWidth) * 100));
}
}, [shrink, hide, containerWidth]);
const handleSplitPaneChange = (newSizes: number[]) => {
console.log('New sizes:', newSizes);
setSizes(newSizes);
};
return (
<motion.div
className={`w-screen h-[calc(100vh-155px)] overflow-hidden absolute top-0 ${shrink || hide ? '-z-10' : 'z-10'}`}
initial={{ marginTop: 155 }}
animate={{ marginTop: shrink ? 0 : 155 }}
>
<motion.div
ref={containerRef}
className="h-[calc(100vh-155px)] w-full absolute right-0 origin-top-right"
initial={{
height: "calc(100vh-155px)",
transform: "translateX(0%) scale(1)",
top: 0,
right: 0,
opacity: 1,
}}
animate={{
transform: shrink ? `translateX(0%) scale(${scaleFactor})` : `translateX(0%) scale(1)`,
top: hide ? "100%" : shrink ? 24 + scaledTopOffset : 0,
right: shrink ? 46 + scaledRightOffset : 0,
opacity: hide ? 0 : 1,
transition: { ease: "linear" },
}}
>
<SplitPane
style={{ width: '100%', height: '100%' }}
split="vertical"
sizes={sizes}
onChange={handleSplitPaneChange}
resizerSize={0}
onDragStart={() => console.log("Starting drag")}
onDragEnd={() => console.log("Stopping drag")}
sashRender={() => (
<div className="flex h-full items-center">
Sash Render
</div>
)}
>
<Pane
minSize={minLeftPaneWidth}
maxSize="100%"
className="w-full h-full pl-0 pr-5 pb-8 overflow-visible"
>
{some code...}
</Pane>
<Pane
minSize={minRightPaneWidth}
maxSize="100%"
className="w-full h-full pl-5 pr-0 pb-8 overflow-visible"
>
{some code...}
</Pane>
</SplitPane>
</motion.div>
</motion.div>
);
Upvotes: 0
Views: 23