# Resizable

- Page: <https://kznlabs.github.io/labsUI/components/resizable>

## Resizable (`resizable`, component)

Split panes for admin layouts, docs and editors. Hairline dividers with a wide grab area follow the pointer; collapsible panels snap shut past half their minimum. Dividers are APG window splitters: arrows step, Home/End jump to the limits, Enter or double-click collapses with a spring. Groups nest.

- Install: `npx @kznlabs/labsui add resizable`
- Docs: <https://kznlabs.github.io/labsUI/components/resizable>
- Brings: utils
- npm: clsx@^2.1.1, motion@14.7.1, tailwind-merge@^3.7.0

### API

- `<ResizablePanelGroup>` (+ <div> props): Split panes (admin layouts, docs, editors). Sizes are % of the group. Handles are APG window
splitters: arrows step, Home/End jump to the limits, Enter collapses a collapsible neighbor.
Drag follows the pointer; keys and toggles spring. Panels and handles find their order in the
DOM, so wrappers and Server Component parents work. Until hydration the layout is plain CSS
(`defaultSize` as a flex basis, the others share the rest), so SSR already shows it.
  - `direction?: Direction` = `"horizontal"`: "horizontal": panels side by side. "vertical": stacked.
  - `keyboardStep?: number` = `5`: % per arrow key press.
  - `onLayout?: (sizes: number[]) => void`: Final sizes after each drag, key or toggle, e.g. to save them in a cookie for SSR.
- `<ResizablePanel>` (+ <div> props)
  - `collapsedSize?: number` = `0`: Share in % when collapsed (default 0), e.g. an icon rail.
  - `collapsible?: boolean` = `false`: Dragging past half the minimum snaps it shut; Enter or double-click on the handle toggles.
  - `defaultSize?: number`: Starting share of the group in %. Panels without one split what is left evenly.
  - `maxSize?: number` = `100`: Largest size in % of the group.
  - `minSize?: number` = `10`: Smallest share in % (default 10).
- `<ResizableHandle>` (+ <div> props): The divider between two panels. `withHandle` adds a visible grip.
  - `withHandle?: boolean`: Visible grip in the middle of the divider.

- `type Direction = "horizontal" | "vertical"`

### Usage

```tsx
<ResizablePanelGroup direction="horizontal"><ResizablePanel defaultSize={25} minSize={15} collapsible>…</ResizablePanel><ResizableHandle withHandle /><ResizablePanel>…</ResizablePanel></ResizablePanelGroup>
```

### Example: admin-layout.tsx

```tsx
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable";

export function AdminLayout({ nav, log, children }: {
  nav: React.ReactNode;
  log: React.ReactNode;
  children: React.ReactNode;
}) {
  return (
    <ResizablePanelGroup
      className="h-dvh"
      onLayout={(sizes) => {
        document.cookie = `layout=${JSON.stringify(sizes)}; path=/`;
      }}
    >
      <ResizablePanel defaultSize={22} minSize={15} maxSize={40} collapsible>
        {nav}
      </ResizablePanel>
      <ResizableHandle aria-label="Resize navigation" withHandle />
      <ResizablePanel>
        <ResizablePanelGroup direction="vertical">
          <ResizablePanel defaultSize={70}>{children}</ResizablePanel>
          <ResizableHandle aria-label="Resize log" />
          <ResizablePanel minSize={15} collapsible>
            {log}
          </ResizablePanel>
        </ResizablePanelGroup>
      </ResizablePanel>
    </ResizablePanelGroup>
  );
}
```
