A scrollable region with a thin themed scrollbar, reachable by keyboard, with optional fades at the edges that still have content.
import { ScrollArea } from "@rdloom/react";
const items = Array.from({ length: 20 }, (_, i) => `Deployment ${i + 1}`);
export default function ScrollAreaVerticalListExample() {
return (
<div className="flex w-full justify-center">
<ScrollArea label="Recent deployments" className="h-56 w-full max-w-sm border border-[var(--rd-color-border-default)]">
<ul className="flex flex-col">
{items.map((name) => (
<li key={name} className="border-b border-[var(--rd-color-border-default)] px-4 py-3 text-sm last:border-b-0">
{name}
</li>
))}
</ul>
</ScrollArea>
</div>
);
}Installation
npx rdloom add scroll-areaCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/scroll-area.jsonWorks, but without upgrade tracking.
Usage
import { ScrollArea } from "@rdloom/react";
<div className="flex w-full justify-center">
<ScrollArea label="Recent deployments" className="h-56 w-full max-w-sm border border-[var(--rd-color-border-default)]">
<ul className="flex flex-col">
{items.map((name) => (
<li key={name} className="border-b border-[var(--rd-color-border-default)] px-4 py-3 text-sm last:border-b-0">
{name}
</li>
))}
</ul>
</ScrollArea>
</div>Horizontal tags
import { ScrollArea } from "@rdloom/react";
const tags = ["Design", "Engineering", "Marketing", "Finance", "Support", "Legal", "People", "Security", "Data", "Sales", "Research"];
export default function ScrollAreaHorizontalTagsExample() {
return (
<div className="flex w-full justify-center">
<ScrollArea label="Teams" orientation="horizontal" className="w-[24rem] max-w-full">
<ul className="flex w-max gap-2 pb-3">
{tags.map((tag) => (
<li key={tag} className="whitespace-nowrap rounded-full border border-[var(--rd-color-border-default)] px-3 py-1 text-sm">
{tag}
</li>
))}
</ul>
</ScrollArea>
</div>
);
}Both directions
import { ScrollArea } from "@rdloom/react";
const columns = ["Name", "Region", "Plan", "Seats", "Owner", "Created", "Renews", "Status"];
const rows = Array.from({ length: 16 }, (_, i) => i + 1);
export default function ScrollAreaBothDirectionsExample() {
return (
<div className="flex w-full justify-center">
<ScrollArea label="Accounts table" orientation="both" className="h-56 w-full max-w-md border border-[var(--rd-color-border-default)]">
<table className="w-max min-w-full border-collapse text-sm">
<thead>
<tr>
{columns.map((c) => (
<th key={c} scope="col" className="whitespace-nowrap px-4 py-2 text-start font-medium">
{c}
</th>
))}
</tr>
</thead>
<tbody>
{rows.map((r) => (
<tr key={r} className="border-t border-[var(--rd-color-border-default)]">
{columns.map((c) => (
<td key={c} className="whitespace-nowrap px-4 py-2">
{c} {r}
</td>
))}
</tr>
))}
</tbody>
</table>
</ScrollArea>
</div>
);
}API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
orientationThe directions that scroll. | "vertical" | "horizontal" | "both" | "vertical" |
labelAccessible name of the region. Required unless aria-labelledby points at a heading. | string | none |
showFadesFade the edges that still have content beyond them. | boolean | true |
childrenrequiredThe scrolling content. | node | none |
Accessibility
Role region, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
- Tab moves focus to the region
- Arrow keys, Page Up, Page Down, Home and End scroll it
Screen readers announce
- Announced as a region with its label
What your code must do
- The region is focusable (tabIndex 0) so keyboard users can scroll it
- The region has an accessible name from label or aria-labelledby
- A visible focus ring shows when it has keyboard focus
- Edge fades are decoration and never hide content permanently
Guidelines
Use it when
- A fixed-height list, log or table that scrolls inside the page
- A row of tags or chips wider than its container
Avoid it when
- The whole page scrolls: leave it to the browser
- Content that fits: do not add a scroller
Don't
- Nesting scroll areas in the same direction
- Hiding the scrollbar entirely
- A region with no label
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-border-strong--rd-color-focus-ring--rd-radius-control