ionian/packages/client/src/components/layout/layout.tsx
2024-04-06 01:03:56 +09:00

49 lines
No EOL
1.7 KiB
TypeScript

import { useLayoutEffect, useState } from "react";
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "../ui/resizable";
import { NavList } from "./nav";
interface LayoutProps {
children?: React.ReactNode;
}
export default function Layout({ children }: LayoutProps) {
const MIN_SIZE_IN_PIXELS = 70;
const [minSize, setMinSize] = useState(MIN_SIZE_IN_PIXELS);
useLayoutEffect(() => {
const panelGroup = document.querySelector('[data-panel-group-id="main"]');
const resizeHandles = document.querySelectorAll(
"[data-panel-resize-handle-id]"
);
if (!panelGroup || !resizeHandles) return;
const observer = new ResizeObserver(() => {
let width = panelGroup?.clientWidth;
if (!width) return;
width -= [...resizeHandles].reduce((acc, resizeHandle) => acc + resizeHandle.clientWidth, 0);
// Minimum size in pixels is a percentage of the PanelGroup's height,
// less the (fixed) height of the resize handles.
setMinSize((MIN_SIZE_IN_PIXELS / width) * 100);
});
observer.observe(panelGroup);
for (const resizeHandle of resizeHandles) {
observer.observe(resizeHandle);
}
return () => {
observer.disconnect();
};
}, []);
return (
<ResizablePanelGroup direction="horizontal" id="main">
<ResizablePanel minSize={minSize} collapsible maxSize={minSize}>
<NavList />
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel >
{children}
</ResizablePanel>
</ResizablePanelGroup>
);
}