Scroll Area
A scroll container with a custom, fully stylable scrollbar. The native scrollbar is hidden; the Scrollbar and Thumb reflect the scroll position and support dragging.
Features
Example
Notifications
24- MC
Maya Chen mentioned you in a comment
1m ago
- LP
Leo Park requested your review
2m ago
- RS
Ravi Singh assigned you a task
3m ago
- TD
Tess Doyle shared a document
4m ago
- MC
Maya Chen mentioned you in a comment
5m ago
- LP
Leo Park requested your review
6m ago
- RS
Ravi Singh assigned you a task
7m ago
- TD
Tess Doyle shared a document
8m ago
- MC
Maya Chen mentioned you in a comment
9m ago
- LP
Leo Park requested your review
10m ago
- RS
Ravi Singh assigned you a task
11m ago
- TD
Tess Doyle shared a document
12m ago
- MC
Maya Chen mentioned you in a comment
13m ago
- LP
Leo Park requested your review
14m ago
- RS
Ravi Singh assigned you a task
15m ago
- TD
Tess Doyle shared a document
16m ago
- MC
Maya Chen mentioned you in a comment
17m ago
- LP
Leo Park requested your review
18m ago
- RS
Ravi Singh assigned you a task
19m ago
- TD
Tess Doyle shared a document
20m ago
- MC
Maya Chen mentioned you in a comment
21m ago
- LP
Leo Park requested your review
22m ago
- RS
Ravi Singh assigned you a task
23m ago
- TD
Tess Doyle shared a document
24m ago
Anatomy
import { ScrollArea } from '@wire-ui/react'
<ScrollArea.Root>
<ScrollArea.Viewport>
{/* long content */}
</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="vertical">
<ScrollArea.Thumb />
</ScrollArea.Scrollbar>
</ScrollArea.Root>Styling
The Viewport hides the native scrollbar (scrollbar-width: none) and sets overflow: auto. The Scrollbar is absolutely positioned along its edge and the Thumb is sized/positioned as a percentage of the scrollable content. Style the track via Scrollbar and the draggable handle via Thumb; add touch-none select-none to prevent text selection while dragging.
<ScrollArea.Scrollbar
orientation="vertical"
className="flex w-2.5 touch-none select-none p-0.5 data-[state=hidden]:opacity-0"
>
<ScrollArea.Thumb className="flex-1 rounded-full bg-black/70 hover:bg-black" />
</ScrollArea.Scrollbar>Using data attributes
Scrollbar sets data-state ("visible" / "hidden") reflecting whether the content overflows, and data-orientation. Thumb sets data-orientation. The Viewport, Scrollbar, and Thumb also carry identifier attributes (data-scroll-area-viewport, data-scroll-area-scrollbar, data-scroll-area-thumb) for targeting.
[data-scroll-area-scrollbar][data-state="hidden"] { opacity: 0; }
[data-scroll-area-thumb][data-orientation="horizontal"] { /* … */ }Root props
Accepts all native <div> attributes. Root is set to position: relative so scrollbars can anchor to its edges.
Viewport props
Accepts all native <div> attributes. The scrollable content goes inside. Sets overflow: auto and hides the native scrollbar.
Scrollbar props
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | 'vertical' | 'horizontal' | 'vertical' | Which axis this scrollbar controls |
forceMount | boolean | false | Render even when the content doesn’t overflow |
Also accepts all native <div> attributes.
Thumb props
Accepts all native <div> attributes. Size and position are computed automatically; pointer handlers drive drag-to-scroll.
Data attributes
| Attribute | Element | Values |
|---|---|---|
data-state | Scrollbar | "visible" / "hidden" |
data-orientation | Scrollbar, Thumb | "vertical" / "horizontal" |
data-scroll-area-viewport | Viewport | Present (identifier) |
data-scroll-area-scrollbar | Scrollbar | Present (identifier) |
data-scroll-area-thumb | Thumb | Present (identifier) |
Accessibility
- The
Viewportis a natively scrollable region, so keyboard scrolling and wheel/trackpad behavior work as usual. - The custom scrollbar is supplementary; content remains reachable without it.