Scrollable
A scroll container with a consistently styled custom scrollbar. Supports vertical, horizontal, or both-axis scrolling with optional smooth scroll and persistent scrollbar gutter.
Overview
Scrollable wraps any content in a <div> with controlled overflow and a custom scrollbar style. height and width are set as inline styles, so you can use any CSS value (px, %, vh, etc.).
Import
import { Scrollable } from '@unflow/ui/components/Scrollable';Props
| Prop | Type | Default | Description |
|---|---|---|---|
direction | 'vertical' | 'horizontal' | 'both' | — | Scroll axis. When omitted, both axes scroll. |
height | string | — | Container height (CSS value) |
width | string | — | Container width (CSS value) |
smooth | boolean | false | Enables scroll-behavior: smooth |
persistent | boolean | false | Reserves gutter space for the scrollbar (scrollbar-gutter: stable) |
All standard HTMLDivElement props are forwarded to the container.
Vertical scroll
<Scrollable direction="vertical" height="160px">
{items.map((item) => <div key={item.id}>{item.label}</div>)}
</Scrollable>Horizontal scroll
<Scrollable direction="horizontal" width="300px">
<div style={{ width: 'max-content', display: 'flex', gap: '12px' }}>
{cards.map((card) => <Card key={card.id} {...card} />)}
</div>
</Scrollable>For horizontal scroll, make the inner content wider than the container. Use width: max-content or a fixed width on the inner element.
Smooth scrolling
<Scrollable direction="vertical" height="300px" smooth>
{longContent}
</Scrollable>Smooth scroll is useful for programmatic scroll (e.g. .scrollTo()) — user drag-scroll always feels instant regardless.
Persistent gutter
<Scrollable direction="vertical" height="300px" persistent>
{content}
</Scrollable>persistent reserves gutter space even when the scrollbar isn't visible, preventing layout shifts as content grows in/out of overflow.
Accessibility
- The container has no semantic role — it's a layout primitive.
- Ensure scrollable regions are reachable via keyboard (Tab focus should enter the container, then arrow keys scroll).
- If the scrollable region contains interactive elements, they will be naturally Tab-navigable.