

# LayoutPanel

Side panel for `Layout` start/end slots. Supports fixed width, `useResizable`
integration, and responsive `overlay` / `hidden` modes below a breakpoint.

## Examples

### Default

```tsx
import { useState } from 'react';
import {
  Button,
  Layout,
  LayoutContent,
  LayoutPanel,
  ResizeHandle,
  useResizable,
} from '@var-ui/react';

const { end } = useResizable({
  regions: { end: { defaultWidth: 280, minWidth: 220, maxWidth: 400 } },
});

<Layout
  height="auto"
  padding={0}
  content={<LayoutContent padding={0}>{/* list */}</LayoutContent>}
  end={
    <>
      <LayoutPanel resizable={end} hasDivider label="Details" role="complementary">
        Inspector
      </LayoutPanel>
      <ResizeHandle {...end.handleProps} />
    </>
  }
/>
```

```astro
---
import { Layout, LayoutContent, LayoutPanel } from '@var-ui/astro';
---

<Layout height="auto" padding={0}>
  <LayoutPanel slot="start" side="start" width={180} hasDivider>Nav</LayoutPanel>
  <LayoutContent>Main</LayoutContent>
  <LayoutPanel slot="end" side="end" width={240} hasDivider>Inspector</LayoutPanel>
</Layout>
```

```html
<!-- Static shell — resize requires React -->
```

## Props

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| children | ReactNode | no |  |  |
| className | string \| undefined | no |  |  |
| defaultOpen | boolean \| undefined | no | false | Initial open state for uncontrolled `responsive` usage. |
| hasDivider | boolean \| undefined | no | false |  |
| isOpen | boolean \| undefined | no |  | Controlled open state for `responsive` modes — omit to let the panel manage it internally. |
| isScrollable | boolean \| undefined | no | true |  |
| label | string \| undefined | no |  | Accessible name; paired with `role="region"` by default when set. |
| onOpenChange | ((open: boolean) => void) \| undefined | no |  |  |
| padding | LayoutPadding \| undefined | no |  | Only `0` (seamless) is distinct from the inherited default. |
| resizable | UseResizableResult \| undefined | no |  | Binds `useResizable()`'s result — reads `width` and ignores the `width` prop. When `isCollapsed` is true the panel unmounts (pair with `ResizeHandle` to expand). |
| responsive | LayoutPanelResponsive \| undefined | no |  | Collapses the panel to `overlay` or `hidden` below a breakpoint. Inert above it. |
| role | string \| undefined | no |  |  |
| width | string \| number \| undefined | no |  | Ignored when `resizable` is provided — `resizable.width` wins. |

## Accessibility

Set `role` (e.g. `complementary`, `navigation`) and `label` when the panel is a landmark.
