Scrollable regions with a custom thumb.
Also known as: custom scrollbar, scroll container, scrollport, custom scroll area
Install with the CLI, or copy the component source into your project.
Add scroll-area (npm)
1npx --yes -p @default-file/ui df-ui add scroll-area
Wider overlay thumb, inset from the edge. Always visible while content overflows.
Scrollable row 1
Scrollable row 2
Scrollable row 3
Scrollable row 4
Scrollable row 5
Scrollable row 6
Scrollable row 7
Scrollable row 8
Scrollable row 9
Scrollable row 10
Scrollable row 11
Scrollable row 12
Set orientation to horizontal to track the left/right axis. The thumb runs along the bottom edge and stays visible while content overflows. Use `both` for content that overflows on either axis.
Thin accent flush with the trailing edge. Use beside a column divider or sidebar border so the thumb reads as part of that line.
Sections
Nav item 1
Nav item 2
Nav item 3
Nav item 4
Nav item 5
Nav item 6
Nav item 7
Nav item 8
Nav item 9
Nav item 10
Nav item 11
Nav item 12
Nav item 13
Nav item 14
Nav item 15
Nav item 16
Move the scrollbar to another edge with the side prop. The vertical bar honours left or right. The horizontal bar honours top or bottom. Setting side to left flushes the thumb against a leading divider, ideal for a right-hand table of contents whose border sits on its left.
On this page
Section 1
Section 2
Section 3
Section 4
Section 5
Section 6
Section 7
Section 8
Section 9
Section 10
Section 11
Section 12
Section 13
Section 14
Section 15
Section 16
On the edge variant, switch the thumb corners between rounded pill ends and square, flat ends with the thumbShape prop. The prop works on the default variant too.
rounded
Nav item 1
Nav item 2
Nav item 3
Nav item 4
Nav item 5
Nav item 6
Nav item 7
Nav item 8
Nav item 9
Nav item 10
Nav item 11
Nav item 12
Nav item 13
Nav item 14
Nav item 15
Nav item 16
flat
Nav item 1
Nav item 2
Nav item 3
Nav item 4
Nav item 5
Nav item 6
Nav item 7
Nav item 8
Nav item 9
Nav item 10
Nav item 11
Nav item 12
Nav item 13
Nav item 14
Nav item 15
Nav item 16
Scrollable region with a custom overlay thumb. By default the thumb appears on hover or while scrolling and hides when idle; set visibility to always to keep it on whenever the content overflows. Track inset follows space: auto reserves it only when that axis overflows. space none overlays without inset, except on the default variant with hover where auto is forced so the wider bar cannot jerk the layout. Track ends stay inset so thumbs are not clipped by rounded overflow shells.
| Prop | Type | Default | Notes |
|---|---|---|---|
| variant | "default" | "edge" | "default" | Scrollbar appearance. default is a wider overlay thumb inset by --df-scrollbar-track-inset. edge is a thin accent whose content-facing inset is --df-scrollbar-edge-inset (default 0, flush). Use edge next to a sidebar or column divider so the thumb reads as part of that line. |
| thumbShape | "rounded" | "flat" | "rounded" | Thumb corner shape. Works on both variants. `rounded` gives pill ends; `flat` gives square ends, handy with the `edge` variant so the thumb reads as a straight segment of the divider. |
| orientation | "vertical" | "horizontal" | "both" | "vertical" | Scroll axis for thumbs and viewport overflow. `vertical` scrolls up/down and clips horizontal overflow; `horizontal` scrolls left/right and clips vertical overflow; `both` allows either axis when content overflows. |
| side | "left" | "right" | "top" | "bottom" | "right" (vertical) / "bottom" (horizontal) | Which edge the scrollbar sits on. The vertical bar honours `left`/`right`; the horizontal bar honours `top`/`bottom`. Pair with `edge` to flush the thumb against a leading divider, for example a right hand table of contents whose border sits on its left. |
| visibility | "hover" | "always" | "hover" | When the thumb is shown. `hover` fades it in on hover or while scrolling and hides it when idle; `always` keeps it visible whenever the content overflows. |
| space | "auto" | "none" | "auto" | Whether the viewport reserves track inset. auto adds inset when that axis overflows, and for the default variant with visibility hover so the wider bar does not jerk layout when it appears. none overlays the thumb with no inset, which keeps the viewport and overlay layers the same client size. |
| width | number | - | Scrollbar and thumb thickness in pixels (width for the vertical bar, height for the horizontal bar). Overrides the variant default (~10px for `default`, 3px for `edge`). |
| viewportClassName | string | - | Classes on the scrollable viewport (the element that actually scrolls). |
| viewportRef | Ref<HTMLDivElement> | - | Ref to the scrollable viewport. Use this for imperative scroll control when the area owns page or panel scroll. |
| overlay | ReactNode | - | Optional layer painted above the viewport and below scrollbar thumbs. Use for interactive surfaces that must share the scrollport box, such as a transparent editor textarea over highlighted content. |
| overlayClassName | string | - | Classes on the overlay layer wrapper. |
| className | string | - | Classes on the outer scroll area root. Set a fixed height here (or via style) so content can overflow. |
| style | CSSProperties | - | Inline styles on the root. Often used to set height when className is not enough. |
| children | ReactNode | - | Scrollable content inside the viewport. |
Standalone scrollbar part when composing manually. Prefer ScrollArea for typical use. It owns thumb sizing and show/hide.
| Prop | Type | Default | Notes |
|---|---|---|---|
| orientation | "vertical" | "horizontal" | "vertical" | Scrollbar axis. |
| className | string | - | Additional styles on the scrollbar track. |
Theme defaults live on :root. Override these globally or on a local host.
| Token | Type | Default | Notes |
|---|---|---|---|
| --df-scrollbar-thickness | CSS length | 3px | Default thumb thickness for the edge variant. |
| --df-scrollbar-track-inset | CSS length | calc(2 * var(--spacing-unit)) | Inset of the default variant track from the scroll shell edges. Also used for track end inset on both variants. |
| --df-scrollbar-edge-inset | CSS length | 0px | Content-facing inset for the edge variant. Default 0 keeps the accent flush. Hosts may override on the ScrollArea root. |
| --df-scrollbar-track-size | CSS length | calc(2.5 * var(--spacing-unit)) | Default variant track thickness reserved when space is auto. |
| --border | CSS color | var(--df-neutral-100) | Default variant thumb fill. |
| --foreground | CSS color | var(--df-neutral-900) | Edge variant thumb mix base. |