Layout
ScrollArea
A scrollable region with slim, themed scrollbars in place of the native ones.
<UiScrollArea />Options
One block per prop — what it does, and what it looks like set.
Orientation
orientation picks the axes that scroll. The scroll area needs a bounded size on that axis — a height for vertical, a width (usually its container's) for horizontal — or there's nothing to overflow.
The scroll area takes its size from you, not its content: give it an h-* or max-h-* for a vertical axis (a horizontal one is bounded by its container width already). Without one it grows to fit and nothing ever overflows. max-h-* works because the root is a flex column and the viewport a shrinkable flex item — a plain h-full viewport would resolve against an auto height and never scroll.
Type
type decides when the bars show: hover while the pointer's over the area or it's scrolling, scroll only while scrolling, auto whenever the content overflows, and always even when it doesn't.
Scrolling itself stays native — wheel, touch, keyboard, find-in-page and scrollIntoView all act on the real viewport. Only the scrollbar is replaced: the native one is hidden with scrollbar-none and the themed bar is drawn from the viewport's own scroll metrics, re-read on every scroll and whenever a ResizeObserver sees the viewport or content change size.
Scroll hide delay
scrollHideDelay is how long the bars linger after scrolling stops or the pointer leaves, for hover and scroll.
Size
size sets the track's thickness. The thumb fills whatever the track gives it.
Fade
fade masks the content out along each edge there's more to scroll toward, and drops the fade once you've reached that end. It's a mask rather than an overlay, so it works on any background.
fade is a CSS mask-image, so it fades to transparent against any background — but it also masks the focus ring and anything else drawn inside the viewport near an edge. With both axes scrolling the two gradients are intersected with mask-composite.
Focusable
focusable makes the viewport a tab stop so keyboard users can scroll it with the arrow keys. Leave it on unless everything inside is already focusable.
Label
label names the scrolling region, and announces it as a landmark under that name.
Examples
The component in real use: compositions that answer "how do I build X with this", rather than one prop at a time.
Both axes
both scrolls a grid wider and taller than its box. Each bar stops short of the corner the other runs into.
Max height
A max-h-* bounds it as well as a fixed height does: short content collapses the area to fit, long content scrolls.
Scrolling from code
The instance exposes scrollTo, scrollToTop and scrollToBottom, plus the viewport element itself.
@scroll is the viewport's native event re-emitted, since listeners on the root would never see it (the root doesn't scroll). For anything else — scrollTop, an IntersectionObserver root, scrollIntoView targets — the exposed viewport is the element that actually scrolls.
API Reference
Generated from the component's source — props, slots and emits as the component actually declares them.
Props
"vertical" | "horizontal" | "both"'vertical'"auto" | "always" | "hover" | "scroll"'hover'number600booleanfalsebooleantruestringSlots
defaultEmits
scroll[event: Event]Types
type Axis = "x" | "y";