# Scroll Area

A scrollable region with slim, custom-styled scrollbars.

Scroll Area is an open-source component from suiss/ui for React. The @esuiss/ui CLI copies its source into your project, so you own the code.

Source: https://ui.suiss.app/docs/components/scroll-area

**React**

**Example**

```tsx
import { ScrollArea } from "@/components/ui/scroll-area"
import { Separator } from "@/components/ui/separator"

const releases = Array.from({ length: 40 }, (_, index) => `v2.${40 - index}.0`)

export default function ScrollAreaDemo() {
  return (
    <ScrollArea className="h-72 w-48 rounded-2xl border">
      <div className="p-4">
        <h4 className="mb-4 text-sm font-medium">Releases</h4>
        {releases.map((release) => (
          <div key={release}>
            <div className="text-sm">{release}</div>
            <Separator className="my-2" />
          </div>
        ))}
      </div>
    </ScrollArea>
  )
}
```

Scroll Area wraps the scroll area primitive of the chosen base. `ScrollArea` renders the root, a focusable viewport for your content, a vertical `ScrollBar` and a corner. Add a horizontal `ScrollBar` as a child when content scrolls sideways.

Use Scroll Area to give overflowing content a consistent scrollbar across platforms. For chat transcripts that should open at the latest message, use Message Scroller.

## Installation

### CLI

```bash title="Terminal"
npx shadcn@latest add @esuiss/scroll-area
```

Works in any project with a `components.json`. See [Installation](https://ui.suiss.app/docs/installation#add-components) for the one-line registry setup. Or use the suiss/ui CLI:

```bash title="Terminal"
npx @esuiss/ui@latest add scroll-area
```

### Manual

1. Install the dependencies and add the [`cn` helper](https://ui.suiss.app/docs/installation#the-cn-helper):

```bash title="Terminal"
npm install @base-ui/react
```

2. Copy the source into `components/ui/scroll-area.tsx`:

```tsx title="components/ui/scroll-area.tsx"
"use client"

import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area"
import { cn } from "@/lib/utils"

function ScrollArea({
  className,
  children,
  ...props
}: ScrollAreaPrimitive.Root.Props) {
  return (
    <ScrollAreaPrimitive.Root
      data-slot="scroll-area"
      className={cn("relative", className)}
      {...props}
    >
      <ScrollAreaPrimitive.Viewport
        data-slot="scroll-area-viewport"
        className="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1"
      >
        {children}
      </ScrollAreaPrimitive.Viewport>
      <ScrollBar />
      <ScrollAreaPrimitive.Corner />
    </ScrollAreaPrimitive.Root>
  )
}

function ScrollBar({
  className,
  orientation = "vertical",
  ...props
}: ScrollAreaPrimitive.Scrollbar.Props) {
  return (
    <ScrollAreaPrimitive.Scrollbar
      data-slot="scroll-area-scrollbar"
      data-orientation={orientation}
      orientation={orientation}
      className={cn(
        "z-10 flex touch-none p-px transition-colors select-none data-horizontal:mx-2 data-horizontal:mb-1 data-horizontal:h-2.25 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:my-2 data-vertical:me-1 data-vertical:w-2.25 data-vertical:border-s data-vertical:border-s-transparent",
        className
      )}
      {...props}
    >
      <ScrollAreaPrimitive.Thumb
        data-slot="scroll-area-thumb"
        className="relative flex-1 rounded-full bg-border"
      />
    </ScrollAreaPrimitive.Scrollbar>
  )
}

export { ScrollArea, ScrollBar }
```

3. Update the import paths to match your project.

## Usage

```tsx
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"
```

```tsx
<ScrollArea className="h-72 w-48 rounded-2xl border">
  <div className="p-4">
    <h4 className="mb-4 text-sm font-medium">Releases</h4>
    {releases.map((release) => (
      <div key={release}>
        <div className="text-sm">{release}</div>
        <Separator className="my-2" />
      </div>
    ))}
  </div>
</ScrollArea>
```

Give `ScrollArea` a fixed height or width with `className` so its content can overflow. Children render inside the viewport. For horizontal scrolling, make the content wider than the area (for example with `w-max`) and include `ScrollBar` with `orientation="horizontal"`.

## Examples

### Horizontal

A row of album covers that scrolls sideways with a horizontal scrollbar.

**Example**

```tsx
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"

const albums = [
  { title: "Morning Light", artist: "Nora Hale" },
  { title: "Open Roads", artist: "The Fieldnotes" },
  { title: "Paper Moons", artist: "Ivy Grant" },
  { title: "Low Tide", artist: "Harbor Lines" },
  { title: "Glass Garden", artist: "Mira Stone" },
  { title: "Northbound", artist: "Echo Park" },
  { title: "Slow Motion", artist: "Luca Reyes" },
]

export default function ScrollAreaHorizontal() {
  return (
    <ScrollArea className="w-96 rounded-2xl border whitespace-nowrap">
      <div className="flex w-max gap-4 p-4">
        {albums.map((album) => (
          <figure key={album.title} className="w-32 shrink-0">
            <div className="bg-muted aspect-square rounded-xl" />
            <figcaption className="text-muted-foreground pt-2 text-xs">
              <span className="text-foreground font-medium">{album.title}</span>
              <br />
              {album.artist}
            </figcaption>
          </figure>
        ))}
      </div>
      <ScrollBar orientation="horizontal" />
    </ScrollArea>
  )
}
```

## API Reference

- `ScrollArea`
- `ScrollBar`

### ScrollArea

The root that renders the viewport, the vertical scrollbar and the corner.

Also accepts the props of the primitive part it wraps.

### ScrollBar

A scrollbar track and thumb for one orientation, vertical by default.

Also accepts the props of the primitive part it wraps.

## Accessibility

- The viewport is focusable, so keyboard users can Tab to it and scroll with the arrow keys.
- Focus is shown with the standard focus ring around the viewport.
- The custom scrollbars are presentational; native scrolling by wheel, touch and keyboard still works.

## Notes

- Styling hooks: `data-slot` values `scroll-area`, `scroll-area-viewport`, `scroll-area-scrollbar` and `scroll-area-thumb`. Scrollbars expose `data-orientation`.
- The thumb uses the `border` color.
- The viewport inherits the root's border radius, so rounded containers clip their content.

