# Layout Panel

## Usage

Sidebar for navigation, settings, or inspector panels.

```ts
import { LayoutPanel } from '@astryx-vue/core/Layout'
```

`LayoutPanel` is a side region of a `Layout`. It goes in the `start` or `end` slot, keeps its own width, and scrolls independently of `LayoutContent`, so a navigation list or an inspector stays put while the middle of the page moves.

`width` is pixels when it is a number. When a `ResizeHandle` owns the width, pass the `props` from `useResizable` to `resizable` instead and the panel follows the drag. `hasDivider` draws the edge that faces the content; do not draw it when a resize handle already draws a line on that same edge. `isScrollable` is on by default; turn it off when the panel should only grow with its content.

```vue
<script setup lang="ts">
import { Layout, LayoutContent, LayoutPanel } from '@astryx-vue/core/Layout'
import { List, ListItem } from '@astryx-vue/core/List'
</script>

<template>
  <Layout>
    <template #start>
      <LayoutPanel :width="200" role="navigation" label="Sections">
        <List>
          <ListItem is-selected label="Overview" />
          <ListItem label="Analytics" />
          <ListItem label="Settings" />
        </List>
      </LayoutPanel>
    </template>
    <LayoutContent>
      Panel content goes here.
    </LayoutContent>
  </Layout>
</template>
```

## Examples

Common configurations, variations, and states.

### Navigation

A fixed-width side panel holding a navigation list next to the main content. Use LayoutPanel in the start or end slot of Layout for sidebars.

```vue
<script setup lang="ts">
import { Card } from '@astryx-vue/core/Card'
import { Layout, LayoutContent, LayoutPanel } from '@astryx-vue/core/Layout'
import { List, ListItem } from '@astryx-vue/core/List'
</script>

<template>
  <Layout>
    <template #start>
      <LayoutPanel :width="140" role="navigation" label="Sections">
        <List>
          <ListItem is-selected label="Overview" />
          <ListItem label="Analytics" />
          <ListItem label="Settings" />
        </List>
      </LayoutPanel>
    </template>
    <LayoutContent>
      <Card variant="muted" />
    </LayoutContent>
  </Layout>
</template>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `hasDivider` | `boolean` | `false` | Draws a rule on the edge that faces the content. Leave it off when an adjacent `ResizeHandle` already draws a line on that edge. |
| `isScrollable` | `boolean` | `true` | Scrolls the panel when its content is taller than the panel. |
| `label` | `string` | — | Accessible name for the landmark element. |
| `padding` | `SpacingStep` | — | Internal padding using the spacing scale. Overrides the padding the surrounding layout passes down. `0` makes the panel full bleed. |
| `resizable` | `LayoutResizable` | — | The `props` object from `useResizable`. When it is given, the hook owns the width and `width` is ignored. Place a `ResizeHandle` next to the panel and give it the same object. The object carries the region's axis as `_direction` (`'horizontal' \| 'vertical'`), which must match the handle's `direction`. Only `_size` is required, so a hand-built `{ _size: 250 }` still works. |
| `role` | `string` | — | ARIA landmark role, for example `navigation`. |
| `width` | `number \| string` | — | Panel width. Numbers are pixels, strings are used as they are. Ignored when `resizable` is given. |

`SpacingStep` accepts these values:

```ts
type SpacingStep = 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10
```

## Slots

- `default`: the panel content.

## Template ref

`LayoutPanel` exposes `element`.
Its type is `HTMLDivElement | null`.

## Native attributes

The root element receives HTML attributes, `aria-*` attributes, `data-*` attributes, `class`, and `style`. `class` is merged with the component's own classes.
