Panel
Scroll area
Scrolls content inside a fixed box, with a scrollbar styled to the theme.
Import
import { ScrollArea, ScrollBar } from "@booleanpress/ui/scroll-area"Usage
Give the scroll area a size. Content that is taller or wider than the box scrolls inside it.
import { ScrollArea } from "@booleanpress/ui/scroll-area"
export function Events({ events }: { events: string[] }) {
return (
<ScrollArea className="h-56 w-64 rounded-md border">
<ul className="p-4">
{events.map((event) => (
<li key={event}>{event}</li>
))}
</ul>
</ScrollArea>
)
}It draws a vertical scrollbar. For sideways scrolling, add <ScrollBar orientation="horizontal" /> as a child, and make the content wider than the box (w-max). The scrollbar shows while the pointer is over the area or the content scrolls. The area has no padding and no border: give them with className (on the area) or on the content.
Examples
Vertical
A list of 20 events in a box 14 rem tall, scrolled with the wheel, touch or the scrollbar.
Horizontal
A row of mailers wider than the box; ScrollBar with orientation="horizontal" adds the bar.
Accessibility
- Semantics
- A
divfor the area and adivviewport that holds the content. The scrollbars carry no role or name. The content stays in reading order. - Labels
- The area has no role or name. Add
role="region"andaria-labelto the area when the box is a distinct part of the page that people should be able to find. - Focus
- The viewport is not focusable. A keyboard user can scroll it only when content inside it takes focus (a link, a button), because the browser scrolls a focused control into view.
- Known limits
- Content with no focusable control cannot be scrolled from the keyboard in every browser: WCAG 2.1.1 asks for it.
ScrollAreadoes not pass props to its viewport, so it cannot taketabIndex={0}. Put a focusable element in the content, or make the first item focusable. - The 10 px scrollbar is a small target for a pointer; the wheel, touch and trackpad scroll without it.
- Content with no focusable control cannot be scrolled from the keyboard in every browser: WCAG 2.1.1 asks for it.
Keyboard
| Key | Behaviour |
|---|
API
ScrollArea
Renders Radix ScrollArea.Root and passes it every other prop.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | ||
dir | "ltr" | "rtl" | The reading direction. It follows the provider's dir unless set here. | |
scrollHideDelay | number | Milliseconds before the scrollbar hides again (default 600). | |
type | "auto" | "hover" | "always" | "scroll" | When the scrollbar shows: hover (default), scroll, auto or always. |
ScrollBar
Renders Radix ScrollArea.ScrollAreaScrollbar and passes it every other prop.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | ||
forceMount | true | ||
orientation | "horizontal" | "vertical" | vertical | vertical (default) or horizontal. |
Every part takes className, merged with its defaults by cn(), and ref, which reaches the element it renders.
Data attributes: data-slot="scroll-area" (ScrollArea), data-slot="scroll-area-scrollbar" (ScrollBar).
Theming
The tokens its classes read. Change their values in your theme, and it follows.
| Token | Used for |
|---|---|
--border | background |
--ring | focus ring |