/// Utilities
ScrollArea
A scrollable viewport with thin, sharp, hairline scrollbars — on either or both axes, with configurable visibility.
import { ScrollArea } from "@protocore/pds";Basics
Give ScrollArea a bounded height and its content scrolls behind a thin, sharp scrollbar. The hairline track and --pds-border-ctrl thumb replace the OS scrollbar for a consistent look across platforms.
Both axes
Set scrollbars="both" and give the area a bounded width and height to scroll wide content — a log table, a config dump — on both axes with a corner where the scrollbars meet.
Visibility
type controls when scrollbars show: hover (default) reveals them on hover and while scrolling, always keeps them visible, scroll shows them only mid-scroll, and auto shows them whenever the content overflows.
When to use it
Use ScrollArea to give a bounded region a custom, consistent scrollbar — one that matches the sharp, hairline PDS look on every OS instead of the browser's default. It wraps Radix's ScrollArea primitive, which keeps native wheel, touch, and keyboard scrolling intact while restyling the bar. Reach for it around scrollable panels, menus, log viewers, and long option lists. It needs a definite size on the scroll axis (a height for vertical, a width for horizontal) so the content has something to overflow. For simple page-level scrolling, don't wrap the whole document — let the native viewport handle it.
Usage
Do
- Give the ScrollArea a bounded height (or width) so content can overflow and scroll.
- Use scrollbars="both" only when content genuinely overflows on both axes.
- Pick type="always" for dense tools where a hidden scrollbar would hide state.
Don't
- Wrap the entire page in a ScrollArea — leave document-level scrolling native.
- Rely on it without a size constraint; with no overflow there is nothing to scroll.
- Nest ScrollAreas deeply on the same axis; nested wheels trap scrolling.
Accessibility
| Keys | Action |
|---|---|
| Tab | Move focus into the scrollable content. |
| Arrow keys / Page Up / Page Down | Scroll the focused viewport, as with a native scroll region. |
- Wheel, touch, and keyboard scrolling are preserved by the underlying Radix primitive — the custom bar is purely visual.
- The scrollbar thumb carries an enlarged hit target so it stays grabbable despite the thin visual width.
- Reduced-motion users get the same scrolling; only the scrollbar fade honors the OS motion preference.
ScrollArea props
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | — | |
className | string | — | |
rootClassName | string | — | Extra class for the outer Root element. |
scrollbars | enum | y | Which scrollbars to render. |
scrollHideDelay | number | 600 | Delay in ms before hiding the scrollbars in `scroll`/`hover` mode. |
style | CSSProperties | — | |
type | enum | hover | When the scrollbars are shown. - `auto` — visible when the content overflows - `always` — always visible - `scroll` — visible while scrolling - `hover` — visible on hover and while scrolling |