Scroll Area
A scrollable region with custom, consistently styled scrollbars that keep native scrolling behavior.
Default
ScrollArea lets you control the appearance of scrollbars in a scrollable region.
tsx
import { ScrollArea } from "@hummingbirdui/react";
const tags = Array.from({ length: 30 }, (_, i) => `v1.2.0-beta.${30 - i}`);
export default function ScrollAreaDefault() {
return (
<ScrollArea className="mx-auto h-72 w-48 rounded-lg border border-subtle">
<ScrollArea.Viewport className="p-4">
<h6 className="mb-2 text-sm font-semibold">Tags</h6>
{tags.map((tag) => (
<div key={tag} className="border-b border-subtle py-2 text-sm">
{tag}
</div>
))}
</ScrollArea.Viewport>
<ScrollArea.Scrollbar />
</ScrollArea>
);
}Horizontal
Use orientation="horizontal" on the scrollbar to handle horizontally overflowing content.
tsx
import { ScrollArea } from "@hummingbirdui/react";
const artworks = [
{
artist: "Vladimir Malyavko",
art: "https://images.unsplash.com/photo-1494337480532-3725c85fd2ab?q=80&w=600&auto=format&fit=crop",
},
{
artist: "Bailey Zindel",
art: "https://images.unsplash.com/photo-1469474968028-56623f02e42e?q=80&w=600&auto=format&fit=crop",
},
{
artist: "Pablo Heimplatz",
art: "https://images.unsplash.com/photo-1494256997604-768d1f608cac?q=80&w=600&auto=format&fit=crop",
},
{
artist: "Ornella Binni",
art: "https://images.unsplash.com/photo-1465869185982-5a1a7522cbcb?q=80&w=600&auto=format&fit=crop",
},
{
artist: "Tom Byrom",
art: "https://images.unsplash.com/photo-1548516173-3cabfa4607e9?q=80&w=600&auto=format&fit=crop",
},
];
export default function ScrollAreaHorizontal() {
return (
<ScrollArea className="mx-auto w-96 max-w-full rounded-lg border border-subtle">
<ScrollArea.Viewport>
<div className="flex gap-4 p-4">
{artworks.map(({ artist, art }) => (
<figure key={artist} className="shrink-0">
<div className="overflow-hidden rounded-lg">
<img
src={art}
alt={`Photo by ${artist}`}
className="aspect-3/4 h-80 w-auto object-cover"
/>
</div>
<figcaption className="pt-2 text-xs text-muted">
Photo by{" "}
<span className="font-semibold text-default">{artist}</span>
</figcaption>
</figure>
))}
</div>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="horizontal" rounded />
</ScrollArea>
);
}Both directions
tsx
import { ScrollArea, Table } from "@hummingbirdui/react";
const rows = Array.from({ length: 20 }, (_, i) => i + 1);
export default function ScrollAreaBoth() {
return (
<ScrollArea className="mx-auto h-72 w-96 max-w-full rounded-lg border border-subtle">
<ScrollArea.Viewport>
<Table className="w-[40rem]">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Role</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{rows.map((row) => (
<tr key={row}>
<td>{row}</td>
<td>Person {row}</td>
<td>person{row}@example.com</td>
<td>Member</td>
<td>Active</td>
</tr>
))}
</tbody>
</Table>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar />
<ScrollArea.Scrollbar orientation="horizontal" />
<ScrollArea.Corner />
</ScrollArea>
);
}Rounded
Use rounded prop on the scrollbar to round the scrollbar track and thumb.
tsx
import { ScrollArea } from "@hummingbirdui/react";
export default function ScrollAreaRounded() {
return (
<ScrollArea
type="always"
className="mx-auto h-72 w-64 rounded-lg border border-subtle"
>
<ScrollArea.Viewport className="p-4 pe-6">
<p className="text-sm">
The rounded scrollbar keeps the pill-shaped track and thumb from
Hummingbird's <code>scrollbar-rounded</code> utility. Lorem ipsum
dolor sit amet, consectetur adipiscing elit. Integer nec odio.
Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis
sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris.
Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum
lacinia arcu eget nulla. Curabitur sodales ligula in libero. Sed
dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean
quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis
tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi
lectus risus, iaculis vel, suscipit quis, luctus non, massa.
</p>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar rounded />
</ScrollArea>
);
}Always visible
Use type="always" on the scrollbar to keep the scrollbar visible whenever content overflows, instead of showing it on hover.
tsx
import { ScrollArea } from "@hummingbirdui/react";
export default function ScrollAreaAlways() {
return (
<ScrollArea
type="always"
className="mx-auto h-72 w-64 rounded-lg border border-subtle"
>
<ScrollArea.Viewport className="p-4 pe-6">
<p className="text-sm">
With <code>type="always"</code> the scrollbar stays visible
whenever the content overflows, instead of appearing on hover. Lorem
ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio.
Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis
sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris.
Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum
lacinia arcu eget nulla. Curabitur sodales ligula in libero. Sed
dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean
quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis
tristique sem. Proin ut ligula vel nunc egestas porttitor.
</p>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar />
</ScrollArea>
);
}API Reference
ScrollArea is built on the Radix UI Scroll Area primitive. Each part forwards all props to its Radix counterpart.
ScrollArea
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
type | enum | "hover" |
scrollHideDelay | number | 600 |
dir | enum | — |
nonce | string | — |
className | string | — |
ScrollArea.Viewport
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | — |
ScrollArea.Scrollbar
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
orientation | enum | "vertical" |
rounded | boolean | false |
forceMount | boolean | — |
className | string | — |
| Data attribute | Values |
|---|---|
[data-state] | visible | hidden |
[data-orientation] | vertical | horizontal |
ScrollArea.Thumb
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
forceMount | boolean | — |
className | string | — |
| Data attribute | Values |
|---|---|
[data-state] | visible | hidden |
ScrollArea.Corner
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
className | string | — |
Styling
The scroll area component utilizes several CSS variables for customization, defined on the root's scroll-area class. Overriding them restyles the scrollbar size, track, and thumb.
.scroll-area {
--scroll-area-scrollbar-size: --spacing(3);
--scroll-area-thumb-color: var(--background-color-emphasis);
--scroll-area-track-color: var(--background-color-muted);
}