Skip to main content

Module scroll

Module scroll 

Source
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§

FollowState
Whether a follow view is still pinned, and the overflow it last saw.
ScrollbarDrag
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_move filters by type alone — without the id every bar in the window would answer one thumb’s gesture.
ScrollbarState
Where in the thumb a drag was grabbed.
TransientState
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 — AnimationElement pins 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 Animation has no delay.

Functions§

at_bottom
Whether offset is at the end of the scrollable range, within slack.
follow
Keep handle pinned 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 viewport length, as a range from the track’s start — or None when 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 over TRANSIENT_IDLE once the scrolling stops. Hovering the strip or dragging the thumb holds it up. With reduce_motion there is nothing to animate, so it renders as the always-on bar.