Skip to content
Protocore Design Systemv1.6.9

/// Utilities

ScrollArea

A scrollable viewport with thin, sharp, hairline scrollbars — on either or both axes, with configurable visibility.

import { ScrollArea } from "@protocore/pds";
View as Markdown

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.

12:00:00 · relay message 1000 settled in 1 hop

12:01:70 · relay message 1001 settled in 1 hop

12:02:14 · relay message 1002 settled in 1 hop

12:03:21 · relay message 1003 settled in 1 hop

12:04:28 · relay message 1004 settled in 1 hop

12:05:35 · relay message 1005 settled in 1 hop

12:06:42 · relay message 1006 settled in 1 hop

12:07:49 · relay message 1007 settled in 1 hop

12:08:56 · relay message 1008 settled in 1 hop

12:09:30 · relay message 1009 settled in 1 hop

12:00:10 · relay message 1010 settled in 1 hop

12:01:17 · relay message 1011 settled in 1 hop

12:02:24 · relay message 1012 settled in 1 hop

12:03:31 · relay message 1013 settled in 1 hop

12:04:38 · relay message 1014 settled in 1 hop

12:05:45 · relay message 1015 settled in 1 hop

12:06:52 · relay message 1016 settled in 1 hop

12:07:59 · relay message 1017 settled in 1 hop

12:08:60 · relay message 1018 settled in 1 hop

12:09:13 · relay message 1019 settled in 1 hop

12:00:20 · relay message 1020 settled in 1 hop

12:01:27 · relay message 1021 settled in 1 hop

12:02:34 · relay message 1022 settled in 1 hop

12:03:41 · relay message 1023 settled in 1 hop

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.

peer_id region version in_hops out_hops latency peer-2328 eu-central-1 v2.4.0 0 1 12ms peer-2329 eu-central-1 v2.4.1 1 2 13ms peer-232a eu-central-1 v2.4.2 2 3 14ms peer-232b eu-central-1 v2.4.3 3 4 15ms peer-232c eu-central-1 v2.4.4 0 0 16ms peer-232d eu-central-1 v2.4.5 1 1 17ms peer-232e eu-central-1 v2.4.6 2 2 18ms peer-232f eu-central-1 v2.4.7 3 3 19ms peer-2330 eu-central-1 v2.4.8 0 4 20ms peer-2331 eu-central-1 v2.4.9 1 0 21ms peer-2332 eu-central-1 v2.4.10 2 1 22ms peer-2333 eu-central-1 v2.4.11 3 2 23ms peer-2334 eu-central-1 v2.4.12 0 3 24ms peer-2335 eu-central-1 v2.4.13 1 4 25ms peer-2336 eu-central-1 v2.4.14 2 0 26ms peer-2337 eu-central-1 v2.4.15 3 1 27ms peer-2338 eu-central-1 v2.4.16 0 2 28ms peer-2339 eu-central-1 v2.4.17 1 3 29ms peer-233a eu-central-1 v2.4.18 2 4 30ms peer-233b eu-central-1 v2.4.19 3 0 31ms

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.

validator attestation #1 verified

validator attestation #2 verified

validator attestation #3 verified

validator attestation #4 verified

validator attestation #5 verified

validator attestation #6 verified

validator attestation #7 verified

validator attestation #8 verified

validator attestation #9 verified

validator attestation #10 verified

validator attestation #11 verified

validator attestation #12 verified

validator attestation #13 verified

validator attestation #14 verified

validator attestation #15 verified

validator attestation #16 verified

validator attestation #17 verified

validator attestation #18 verified

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

KeysAction
TabMove focus into the scrollable content.
Arrow keys / Page Up / Page DownScroll 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

PropTypeDefaultDescription
asChildboolean
classNamestring
rootClassNamestringExtra class for the outer Root element.
scrollbarsenumyWhich scrollbars to render.
scrollHideDelaynumber600Delay in ms before hiding the scrollbars in `scroll`/`hover` mode.
styleCSSProperties
typeenumhoverWhen the scrollbars are shown. - `auto` — visible when the content overflows - `always` — always visible - `scroll` — visible while scrolling - `hover` — visible on hover and while scrolling

Related

  • ResizablePanelsTwo or more panels sharing an axis, split by hairline handles that drag with the pointer and resize with the arrow keys.
  • PanelA dense bordered console surface with an optional labelled header row and hairline-divided sub-sections.
  • CollapseA single animated collapsible region, opened via open/defaultOpen, with an animated height and reduced-motion support.