Layout

ScrollArea

A scrollable region with slim, themed scrollbars in place of the native ones.

vue
<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.

v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
v1.2.0-beta.30
v1.2.0-beta.29
v1.2.0-beta.28
v1.2.0-beta.27
v1.2.0-beta.26
v1.2.0-beta.25
v1.2.0-beta.24
v1.2.0-beta.23
v1.2.0-beta.22
v1.2.0-beta.21
v1.2.0-beta.20
v1.2.0-beta.19
v1.2.0-beta.18
v1.2.0-beta.17
v1.2.0-beta.16
v1.2.0-beta.15
v1.2.0-beta.14
v1.2.0-beta.13
v1.2.0-beta.12
v1.2.0-beta.11
v1.2.0-beta.10
v1.2.0-beta.9
v1.2.0-beta.8
v1.2.0-beta.7
v1.2.0-beta.6
v1.2.0-beta.5
v1.2.0-beta.4
v1.2.0-beta.3
v1.2.0-beta.2
v1.2.0-beta.1
1
2
3
4
5
6
7
8
9
10
11
12

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.

hover

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

scroll

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

auto

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

always

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

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.

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

Size

size sets the track's thickness. The thumb fills whatever the track gives it.

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.

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.

v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
v1.2.0-beta.30
v1.2.0-beta.29
v1.2.0-beta.28
v1.2.0-beta.27
v1.2.0-beta.26
v1.2.0-beta.25
v1.2.0-beta.24
v1.2.0-beta.23
v1.2.0-beta.22
v1.2.0-beta.21
v1.2.0-beta.20
v1.2.0-beta.19
v1.2.0-beta.18
v1.2.0-beta.17
v1.2.0-beta.16
v1.2.0-beta.15
v1.2.0-beta.14
v1.2.0-beta.13
v1.2.0-beta.12
v1.2.0-beta.11
v1.2.0-beta.10
v1.2.0-beta.9
v1.2.0-beta.8
v1.2.0-beta.7
v1.2.0-beta.6
v1.2.0-beta.5
v1.2.0-beta.4
v1.2.0-beta.3
v1.2.0-beta.2
v1.2.0-beta.1

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.

Bundy UI keeps scrolling native: the viewport is an ordinary overflowing element, so wheel, touch, keyboard and find-in-page all behave exactly as the browser makes them. Only the scrollbar is replaced — the native one is hidden and a slim, themed bar is drawn over the edge instead, sized and positioned from the viewport's own scroll metrics. Drag the thumb, or press anywhere on the track to jump there. The bars fade in with the pointer by default and fade back out once it leaves, so a list at rest shows its content and nothing else. When the area can't scroll at all, no bar is drawn.


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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256

Max height

A max-h-* bounds it as well as a fixed height does: short content collapses the area to fit, long content scrolls.

v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48

Scrolling from code

The instance exposes scrollTo, scrollToTop and scrollToBottom, plus the viewport element itself.

v1.2.0-beta.50
v1.2.0-beta.49
v1.2.0-beta.48
v1.2.0-beta.47
v1.2.0-beta.46
v1.2.0-beta.45
v1.2.0-beta.44
v1.2.0-beta.43
v1.2.0-beta.42
v1.2.0-beta.41
v1.2.0-beta.40
v1.2.0-beta.39
v1.2.0-beta.38
v1.2.0-beta.37
v1.2.0-beta.36
v1.2.0-beta.35
v1.2.0-beta.34
v1.2.0-beta.33
v1.2.0-beta.32
v1.2.0-beta.31
v1.2.0-beta.30
v1.2.0-beta.29
v1.2.0-beta.28
v1.2.0-beta.27
v1.2.0-beta.26
v1.2.0-beta.25
v1.2.0-beta.24
v1.2.0-beta.23
v1.2.0-beta.22
v1.2.0-beta.21
v1.2.0-beta.20
v1.2.0-beta.19
v1.2.0-beta.18
v1.2.0-beta.17
v1.2.0-beta.16
v1.2.0-beta.15
v1.2.0-beta.14
v1.2.0-beta.13
v1.2.0-beta.12
v1.2.0-beta.11
v1.2.0-beta.10
v1.2.0-beta.9
v1.2.0-beta.8
v1.2.0-beta.7
v1.2.0-beta.6
v1.2.0-beta.5
v1.2.0-beta.4
v1.2.0-beta.3
v1.2.0-beta.2
v1.2.0-beta.1

@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

Prop
Type
Default
Description
"vertical" | "horizontal" | "both"
'vertical'
Which axes scroll. The other one is clipped, so content wider than a `vertical` scroll area is cut off rather than pushing a second scrollbar in.
"auto" | "always" | "hover" | "scroll"
'hover'
When the scrollbars show. `hover` shows them while the pointer is over the area or it's being scrolled; `scroll` only while it's scrolling; `auto` whenever the content overflows; `always` even when it doesn't, so the track holds its place in the layout's rhythm.
number
600
How long, in milliseconds, the scrollbars stay visible after scrolling stops or the pointer leaves, for the `hover` and `scroll` types.
"sm" | "md" | "lg"
'md'
The thickness of the scrollbar track — 6, 8 or 10 pixels across.
boolean
false
Fade the content out along every edge there's more to scroll toward, so an overflowing area reads as scrollable before anyone touches it.
boolean
true
Make the viewport a tab stop so it can be scrolled from the keyboard. Only turn it off when every piece of content inside is already focusable — focusing a child scrolls to it anyway.
string
—
An accessible name for the scrolling region. When set, the viewport is announced as a `region` landmark under this name.

Slots

Slot
default

Emits

Event
Payload
Description
scroll
[event: Event]
The viewport's native scroll event, re-emitted from the root.

Types

ts
type Axis = "x" | "y";