# `PhiaUi.Components.ScrollArea`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/components/layout/scroll_area.ex#L1)

ScrollArea component — a styled, accessible scrollable container. Zero JavaScript.

`scroll_area/1` wraps any content in a div with controlled overflow and
styled scrollbars. It uses the `tailwind-scrollbar` plugin (or equivalent)
to apply thin, unobtrusive scrollbar styles that look consistent in both
light and dark mode using semantic Tailwind tokens.

The component is a pure CSS primitive — no JS hook, no event handlers. All
behaviour is handled by the browser's native scroll engine.

## Scrollbar Plugin

The `scrollbar-*` utility classes require the `tailwindcss-scrollbar` package
in the host project's Tailwind config:

    # In your host project
    # Install: npm install --save-dev tailwindcss-scrollbar
    # tailwind.config.js
    module.exports = {
      plugins: [require("tailwindcss-scrollbar")]
    }

Without the plugin, the component still functions — scrolling works — but the
native platform scrollbars are displayed rather than the thin styled versions.

## Orientations

| Value          | CSS Applied                | Best For                            |
|----------------|----------------------------|-------------------------------------|
| `"vertical"`   | `overflow-y-auto h-full`   | Tall content lists, sidebars, feeds |
| `"horizontal"` | `overflow-x-auto w-full`   | Wide tables, code blocks, timelines |
| `"both"`       | `overflow-auto`            | 2D content: maps, large diagrams    |

## Example — Vertical Scroll (Default)

The most common use: a fixed-height container that scrolls when content
exceeds the available height.

    <%# Sidebar navigation with many items %>
    <.scroll_area class="h-[calc(100vh-64px)]">
      <nav>
        <.sidebar_item :for={item <- @nav_items} href={item.path}>
          {item.label}
        </.sidebar_item>
      </nav>
    </.scroll_area>

    <%# Message feed in a chat panel %>
    <.scroll_area class="flex-1 min-h-0">
      <div class="p-4 space-y-3">
        <.chat_message :for={msg <- @messages} message={msg} />
      </div>
    </.scroll_area>

## Example — Limited Height List

Show at most a certain height of content and scroll for the rest:

    <.scroll_area class="max-h-64">
      <ul class="space-y-1">
        <li :for={item <- @items} class="px-3 py-2 hover:bg-muted rounded-md">
          {item.label}
        </li>
      </ul>
    </.scroll_area>

## Example — Horizontal Scroll for Wide Tables

Prevent layout breaking on small screens by wrapping wide tables:

    <.scroll_area orientation="horizontal">
      <table class="min-w-[800px] w-full">
        <thead>...</thead>
        <tbody>...</tbody>
      </table>
    </.scroll_area>

## Example — Both Axes (2D Content)

For content that may exceed bounds in both dimensions:

    <.scroll_area orientation="both" class="h-96 w-full max-w-2xl border rounded">
      <div class="min-w-[1200px] min-h-[600px]">
        <%# Large diagram, map, or canvas-like content %>
      </div>
    </.scroll_area>

## Example — Inside a Popover or Sheet

`scroll_area/1` is commonly used inside `popover_content/1` or `sheet/1` to
constrain long lists in confined spaces:

    <.popover id="assignee-picker">
      <.popover_trigger popover_id="assignee-picker">Assign</.popover_trigger>
      <.popover_content popover_id="assignee-picker">
        <p class="text-sm font-medium mb-2">Select assignee</p>
        <.scroll_area class="max-h-48">
          <.command_item :for={user <- @users} on_click="assign" value={user.id}>
            <.avatar src={user.avatar} alt={user.name} size={:xs} />
            {user.name}
          </.command_item>
        </.scroll_area>
      </.popover_content>
    </.popover>

## Sizing

`scroll_area/1` alone does not restrict height or width — you must provide
a size constraint via the `:class` attribute:

- `class="h-64"` — fixed height of 256px
- `class="max-h-64"` — grows up to 256px, then scrolls
- `class="h-full"` — fills parent container height (parent must have height)
- `class="flex-1 min-h-0"` — fills remaining flex space (flex parent required)

The default `h-full` from `orientation_class/1` assumes the parent has a
defined height. Override with `class="max-h-{n}"` for most use cases.

## Accessibility

- The div itself is not focusable or interactive — it is purely a scroll
  container. Screen reader users navigate the content inside normally.
- If the scrollable region contains interactive content, ensure keyboard
  users can reach all items within (Tab order works through the content).
- For very long lists, consider adding a skip link or grouping mechanism
  so keyboard users can navigate efficiently.

# `scroll_area`

Renders a styled scrollable container.

Scrollbar appearance is controlled by the `scrollbar-thin`,
`scrollbar-track-transparent`, and `scrollbar-thumb-muted-foreground/30`
Tailwind classes. These use semantic color tokens so the scrollbar
automatically adapts to dark mode and custom theme presets.

The `overflow-*` class and the primary dimension class (`h-full` or `w-full`)
are determined by `orientation_class/1` based on the `:orientation` attribute.
Your `:class` override is appended last (via `cn/1`) so it wins in any
conflict.

## Attributes

* `orientation` (`:string`) - Scroll direction(s):
  - `"vertical"` (default) — `overflow-y-auto h-full`; use for lists, feeds, sidebars
  - `"horizontal"` — `overflow-x-auto w-full`; use for wide tables, code blocks
  - `"both"` — `overflow-auto`; use for 2D content (maps, large diagrams)

  Defaults to `"vertical"`. Must be one of `"vertical"`, `"horizontal"`, or `"both"`.
* `class` (`:string`) - Additional CSS classes merged via `cn/1`. Use this to set a height or width
  constraint — the component does not restrict dimensions on its own:
  - `class="h-64"` for a fixed 256px height
  - `class="max-h-64"` to grow up to 256px and then scroll
  - `class="h-full"` to fill the parent container (parent must have height)

  Defaults to `nil`.
* Global attributes are accepted. Extra HTML attributes forwarded to the scroll container `<div>`.
## Slots

* `inner_block` (required) - Scrollable content.

---

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