<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# ScrollArea

A scrolling region with a slim scrollbar that matches the theme, inside a height you set. It keeps the browser's own scrolling, so touch, the mouse wheel, the keyboard and momentum all work; the custom scrollbar is for a mouse and never takes a touch.

```tsx
import { ScrollArea } from "@/components/ouro/scroll-area/scroll-area";
```

## Example

```tsx
<ScrollArea className="h-72" label="Method">
  {steps.map((step) => <Text key={step.id}>{step.text}</Text>)}
</ScrollArea>
<ScrollArea orientation="horizontal" label="Tags">
  <Row gap="sm">{tags.map((tag) => <Badge key={tag}>{tag}</Badge>)}</Row>
</ScrollArea>
```

## Use instead when

- Use plain page scrolling instead for a page's main content, and `Dialog` or `Sheet`, which scroll their own bodies, for long content in an overlay.

## Props

Type: `ScrollAreaProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` (required) | `ReactNode` |  | The content that scrolls. |
| `className` | `string` |  | Layout: the area's height or maximum height, which it scrolls inside (`h-72`, `max-h-80`), and its width and margins. Appearance classes warn in development. |
| `contain` | `boolean` | `false` | Keeps a scroll that reaches the area's end from scrolling the page behind it, for a chat thread or a list inside a dialog. Off by default, so a finger that runs out of a recipe's method keeps scrolling the page. |
| `label` | `string` |  | Names the scrolling region for screen readers ("Method", "Order history"). A keyboard user can focus the region to scroll it, so give it a name when nothing else inside can take focus. |
| `orientation` | `"vertical" \| "horizontal" \| "both"` | `"vertical"` | Which way the content scrolls. `horizontal` keeps a row of tags or cards on one line. |
| `ref` | `Ref<HTMLDivElement>` |  | Reaches the rendered element. |

## Native attributes

Also accepts the attributes in React's `HTMLAttributes` (`id`, `aria-*`, event handlers), passed to the rendered element, except those named on this page.

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `height`: Not a prop. Set the height with a class: `<ScrollArea className="h-72">`.
- `maxHeight`: Not a prop. Set the height with a class: `<ScrollArea className="max-h-80">`.
- `type`: Not a prop. The scrollbar shows while the pointer is over the area or it scrolls, on every device.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`). Your classes always win over Ouro UI's: ScrollArea merges `className` last with `cn` (tailwind-merge), so a class that conflicts with its own replaces it.[^layout-classes]

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.

[^layout-classes]: test:registry/ouro/components/ouro/scroll-area/scroll-area.test.tsx::ScrollArea > passes attributes and a ref to the root, and lets layout classes win verify:testExists(registry/ouro/components/ouro/scroll-area/scroll-area.test.tsx::ScrollArea > passes attributes and a ref to the root, and lets layout classes win)
