# `Plushie.Widget.Scrollable`
[🔗](https://github.com/plushie-ui/plushie-elixir/blob/v0.6.0/lib/plushie/widget/scrollable.ex#L1)

Scrollable container -- wraps child content in a scrollable viewport.

## Props

- `width` (length) -- width of the scrollable area. Default: shrink. See `Plushie.Type.Length`.
- `height` (length) -- height of the scrollable area. Default: shrink.
- `direction` (atom) -- scroll direction: `:vertical` (default), `:horizontal`, or `:both`.
  See `Plushie.Type.Direction`. Setting `:both` enables bidirectional scrolling,
  but per-axis scrollbar customization (independent widths, margins per axis)
  is not yet supported.
- `spacing` (number) -- spacing between scrollbar and content.
- `scrollbar_width` (number) -- width of the scrollbar track in pixels.
- `scrollbar_margin` (number) -- margin around the scrollbar in pixels.
- `scroller_width` (number) -- width of the scroller handle in pixels.
- `scrollbar_color` (hex color) -- color for the scrollbar track background.
- `scroller_color` (hex color) -- color for the scroller thumb.
- `id` (string) -- widget ID for programmatic scroll control via `Plushie.Command`.
- `anchor` (atom) -- scroll anchor: `:start` (default) or `:end` / `:bottom` / `:right`.
  See `Plushie.Type.Anchor`.
- `on_scroll` (boolean) -- when `true`, emits `%WidgetEvent{type: :scroll, id: id, data: viewport}` events on scroll.
  The viewport map contains `absolute_x`, `absolute_y`, `relative_x`, `relative_y`,
  `bounds` (as `{width, height}`), and `content_bounds` (as `{width, height}`).
- `auto_scroll` (boolean) -- when `true`, automatically scrolls to show new content.
- `a11y` (map) -- accessibility overrides. See `Plushie.Type.A11y`.

# `option`

```elixir
@type option() ::
  {:width, Plushie.Type.Length.t()}
  | {:height, Plushie.Type.Length.t()}
  | {:direction, Plushie.Type.Direction.t()}
  | {:spacing, number()}
  | {:scrollbar_width, number()}
  | {:scrollbar_margin, number()}
  | {:scroller_width, number()}
  | {:anchor, Plushie.Type.Anchor.t()}
  | {:on_scroll, boolean()}
  | {:auto_scroll, boolean()}
  | {:scrollbar_color, Plushie.Type.Color.input()}
  | {:scroller_color, Plushie.Type.Color.input()}
  | {:a11y, Plushie.Type.A11y.t() | map() | keyword()}
```

# `t`

```elixir
@type t() :: %Plushie.Widget.Scrollable{
  a11y: Plushie.Type.A11y.t() | nil,
  anchor: Plushie.Type.Anchor.t() | nil,
  auto_scroll: boolean() | nil,
  children: [Plushie.Widget.child()],
  direction: Plushie.Type.Direction.t() | nil,
  height: Plushie.Type.Length.t() | nil,
  id: String.t(),
  on_scroll: boolean() | nil,
  scrollbar_color: Plushie.Type.Color.t() | nil,
  scrollbar_margin: number() | nil,
  scrollbar_width: number() | nil,
  scroller_color: Plushie.Type.Color.t() | nil,
  scroller_width: number() | nil,
  spacing: number() | nil,
  width: Plushie.Type.Length.t() | nil
}
```

# `a11y`

```elixir
@spec a11y(scrollable :: t(), a11y :: Plushie.Type.A11y.t() | map() | keyword()) ::
  t()
```

Sets accessibility annotations.

# `anchor`

```elixir
@spec anchor(scrollable :: t(), anchor :: Plushie.Type.Anchor.t()) :: t()
```

Sets the scroll anchor.

# `auto_scroll`

```elixir
@spec auto_scroll(scrollable :: t(), auto_scroll :: boolean()) :: t()
```

Enables automatic scrolling to show new content.

# `build`

```elixir
@spec build(scrollable :: t()) :: Plushie.Widget.ui_node()
```

Converts this scrollable struct to a `ui_node()` map via the `Plushie.Widget` protocol.

# `direction`

```elixir
@spec direction(scrollable :: t(), direction :: Plushie.Type.Direction.t()) :: t()
```

Sets the scroll direction.

# `extend`

```elixir
@spec extend(
  scrollable :: t(),
  children :: [Plushie.Widget.child()]
) :: t()
```

Appends multiple children to the scrollable.

# `height`

```elixir
@spec height(scrollable :: t(), height :: Plushie.Type.Length.t()) :: t()
```

Sets the scrollable height.

# `new`

```elixir
@spec new(id :: String.t(), opts :: [option()]) :: t()
```

Creates a new scrollable struct with optional keyword opts.

# `on_scroll`

```elixir
@spec on_scroll(scrollable :: t(), on_scroll :: boolean()) :: t()
```

Enables scroll position change events.

# `push`

```elixir
@spec push(scrollable :: t(), child :: Plushie.Widget.child()) :: t()
```

Appends a child to the scrollable.

# `scrollbar_color`

```elixir
@spec scrollbar_color(
  scrollable :: t(),
  scrollbar_color :: Plushie.Type.Color.input()
) :: t()
```

Sets the scrollbar track color.

# `scrollbar_margin`

```elixir
@spec scrollbar_margin(scrollable :: t(), scrollbar_margin :: number()) :: t()
```

Sets the scrollbar margin in pixels.

# `scrollbar_width`

```elixir
@spec scrollbar_width(scrollable :: t(), scrollbar_width :: number()) :: t()
```

Sets the scrollbar track width in pixels.

# `scroller_color`

```elixir
@spec scroller_color(scrollable :: t(), scroller_color :: Plushie.Type.Color.input()) ::
  t()
```

Sets the scroller handle color.

# `scroller_width`

```elixir
@spec scroller_width(scrollable :: t(), scroller_width :: number()) :: t()
```

Sets the scroller handle width in pixels.

# `spacing`

```elixir
@spec spacing(scrollable :: t(), spacing :: number()) :: t()
```

Sets the spacing between scrollbar and content.

# `width`

```elixir
@spec width(scrollable :: t(), width :: Plushie.Type.Length.t()) :: t()
```

Sets the scrollable width.

# `with_options`

```elixir
@spec with_options(scrollable :: t(), opts :: [option()]) :: t()
```

Applies keyword options to an existing scrollable struct.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
