Expand description
A styled scrollbar over gpui’s own scroll handles.
gpui scrolls a div perfectly well and draws nothing while it does, so a
bezel app has no way to show how far down it is. This is that bar, and only
that bar: the caller keeps its own overflow_y_scroll container, because a
wrapper that swallowed the content would have to re-implement layout for it.
div().relative() // the bar is absolute in here
.child(
div()
.id("pane")
.size_full()
.overflow_y_scroll()
.track_scroll(&self.scroll) // gpui's handle, the app's field
.child(content),
)
.child(scroll::scrollbar("pane-bar", &self.scroll, &self.scroll_bar))The bar must span the container it reports on — its track is the viewport,
in the coordinates thumb answers in.
The geometry is transcribed from zed’s own scrollbar (thumb_ranges in
crates/ui/src/components/scrollbar.rs), which is 1722 lines of settings
system around the fifteen that matter. Two of gpui’s conventions are easy to
get backwards and both are load-bearing here: max_offset is the overflow
(content minus viewport, not content), and offset is negative as you
scroll down.
transient is the same bar, shown only while its content moves.
Structs§
- Follow
State - Whether a
followview is still pinned, and the overflow it last saw. - Scrollbar
Drag - The drag payload. Carries the bar’s id because, unlike a split, an app has
several of these on screen at once and
on_drag_movefilters by type alone — without the id every bar in the window would answer one thumb’s gesture. - Scrollbar
State - Where in the thumb a drag was grabbed.
- Transient
State - The show-and-fade state behind
transient: the last frame’s scroll state (a change is activity), a generation counter (a fresh animation id restarts the fade —AnimationElementpins its clock to the id it first laid out with), and the hover flag that holds the thumb up while the pointer is on the strip.
Constants§
- FOLLOW_
SLACK - How close to the bottom still counts as following. A wheel lands on fractional offsets and a re-layout can move the end by a hair; without slack a view would unpin itself for a rounding error nobody asked for.
- MIN_
THUMB - Shortest a thumb may get, however long the document — below this it stops being something a pointer can catch.
- RAIL_
ROOM - What a rail needs beside the content before it will paint at all.
- TRANSIENT_
IDLE - How long the thumb stays after the last scroll before fading — the idle
window is the fade, because the fork’s
Animationhas no delay.
Functions§
- at_
bottom - Whether
offsetis at the end of the scrollable range, withinslack. - follow
- Keep
handlepinned to the bottom of its content while the user leaves it there, and get out of the way the moment they scroll up. - offset_
for_ thumb - The inverse: the scroll offset that puts the thumb’s top at
top. - rail
- A mark per item, the one at the top of the viewport lit — for a pane whose content comes in countable pieces (a transcript’s turns) rather than as one continuous document, where how far down you are matters less than which piece you are on. A press jumps to that piece.
- scrollbar
- The bar: an overlay strip along the right edge of whatever it is laid over, showing nothing at all when the content fits.
- thumb
- Where the thumb sits in a track of
viewportlength, as a range from the track’s start — orNonewhen there is nothing to scroll. - transient
- The same bar as
scrollbar, but it only earns its place while the content moves: activity raises the thumb, and it fades out overTRANSIENT_IDLEonce the scrolling stops. Hovering the strip or dragging the thumb holds it up. Withreduce_motionthere is nothing to animate, so it renders as the always-on bar.