Components
ScrollArea
A scrolling region with a thin themed native scrollbar, for panels, menus, side lists and code blocks of fixed height. Native scrolling and the native scrollbar stay; only its color and width are styled (scrollbar-width thin, scrollbar-color). No custom drawn thumb. The page itself keeps the browser scrollbar.
Preview
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea label="Recent activity" className="h-48 w-64 max-w-full rounded-container border border-border">
<div className="min-w-0">
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 09</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 10</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 11</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 12</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
</div>
</ScrollArea>Usage
When to use
- Keep a long list, panel or code block inside a fixed or maximum height while the page stays still.
- Give a scrollable region a thin native scrollbar that follows the current theme.
When not to use
- The whole page should scroll with its content.
- A list is too long to scan and needs search. Use Combobox.
Variants
orientation
Which axes scroll.
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea label="Recent activity" className="h-48 w-64 max-w-full rounded-container border border-border">
<div className="min-w-0">
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 09</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 10</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 11</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 12</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
</div>
</ScrollArea>
<ScrollArea orientation="horizontal" label="Recent activity" className="h-48 w-64 max-w-full rounded-container border border-border">
<div className="flex gap-md p-md">
<div className="w-40 shrink-0 rounded-container border border-border bg-background-surface p-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="w-40 shrink-0 rounded-container border border-border bg-background-surface p-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="w-40 shrink-0 rounded-container border border-border bg-background-surface p-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="w-40 shrink-0 rounded-container border border-border bg-background-surface p-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="w-40 shrink-0 rounded-container border border-border bg-background-surface p-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="w-40 shrink-0 rounded-container border border-border bg-background-surface p-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
</div>
</ScrollArea>
<ScrollArea orientation="both" label="Recent activity" className="h-48 w-64 max-w-full rounded-container border border-border">
<div className="w-160">
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 09</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 10</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 11</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 12</p>
<p className="text-xs text-text-secondary">Updated workspace settings and shared the latest design with your team.</p>
</div>
</div>
</ScrollArea>type
auto shows the native scrollbar when content overflows; always reserves its space (scrollbar-gutter stable) so content does not shift.
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea label="Recent activity" className="h-48 w-64 max-w-full rounded-container border border-border">
<div className="min-w-0">
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 09</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 10</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 11</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 12</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
</div>
</ScrollArea>
<ScrollArea type="always" label="Recent activity" className="h-48 w-64 max-w-full rounded-container border border-border">
<div className="min-w-0">
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 09</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 10</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 11</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 12</p>
<p className="text-xs text-text-secondary">Updated just now</p>
</div>
</div>
</ScrollArea>Examples
Recent activity
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea className="h-48 w-64 max-w-full rounded-container border border-border" label="Recent activity">
<div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
</div>
</ScrollArea>Horizontal projects
import { Card, CardContent } from "@/components/ui/card"
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea orientation="horizontal" className="h-40 w-64 max-w-full rounded-container border border-border" label="Projects">
<div className="flex gap-md p-md">
<Card className="w-40 shrink-0">
<CardContent>Website</CardContent>
</Card>
<Card className="w-40 shrink-0">
<CardContent>Mobile app</CardContent>
</Card>
<Card className="w-40 shrink-0">
<CardContent>Documentation</CardContent>
</Card>
</div>
</ScrollArea>Both axes
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea orientation="both" className="h-48 w-64 max-w-full rounded-container border border-border" label="Project updates">
<div className="w-160">
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
</div>
</ScrollArea>Reserved scrollbar space
import { ScrollArea } from "@/components/ui/scroll-area"
<ScrollArea type="always" className="max-h-48 w-64 max-w-full rounded-container border border-border" label="All projects">
<div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 01</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 02</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 03</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 04</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 05</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 06</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 07</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
<div className="border-b border-border px-md py-md">
<p className="text-sm font-medium">Project 08</p>
<p className="text-xs text-text-secondary">Updated workspace notes</p>
</div>
</div>
</ScrollArea>Do and don't
Do
- Give the root a height or max height.
- Use in DropdownMenu or Combobox lists only if they need a themed bar; they already scroll natively.
- Provide enough content to overflow the chosen axis. Horizontal content needs a width greater than the viewport and must not shrink.
Don't
- Do not wrap the whole page.
- Do not hide the scrollbar on content that the user must know scrolls without another cue.
Props
| Name | Type | Values | Default | Description |
|---|---|---|---|---|
| orientation | enum | vertical | horizontal | both | vertical | Which axes scroll. |
| type | enum | auto | always | auto | auto shows the native scrollbar when content overflows; always reserves its space (scrollbar-gutter stable) so content does not shift. |
| label | string | - | - | Accessible name for the region when the viewport is focusable. |
| tabIndex | number | - | - | On the viewport: override automatic tab order. By default it takes focus only when it has no visible, enabled focusable children. |
| onScroll | React.UIEventHandler<HTMLDivElement> | - | - | On the viewport: native scroll event handler. |
| style | React.CSSProperties | - | - | On the viewport: inline styles for the native scrolling element. Set the outer dimensions with className. |
| className | string | - | - | On the outer box: supply height, max height, width, borders and corners. The viewport fills this box. |
Slots
| Name | Required | Description |
|---|---|---|
| children | yes | The content that scrolls. |
Anatomy
| Part | Description |
|---|---|
| root | Outer box with a fixed or max height. |
| viewport | The scrolling element with overflow auto and the styled native scrollbar. |
Accessibility
Role: region
| Keys | Action |
|---|---|
| Tab | Focuses the viewport when it has no focusable children, so keyboard users can scroll. |
| Arrow keys / PageUp / PageDown / Home / End | Native scrolling on the enabled axes of the focused viewport. |
- Native scrolling stays: wheel, touch, momentum and find-in-page work.
- Pass aria-label when the viewport is focusable so the region has a name.
- Under reduced motion no smooth scrolling is added.
- The scrollbar is the browser's own, so it keeps its platform behavior (overlay scrollbars on touch, dragging, clicking the track).
Install
npx werewolf-ui add scroll-areaRun npx werewolf-ui init once in your app before adding components. Init sets up tokens, their CSS import and agent rules. Add installs this component and its dependencies while preserving your theme. See Installation for requirements and the alternative registry setup.