Details
```rust
//! Reproduction of the scrollbar-offset bug in bottom-aligned `ListState`.
//!
//! Run with: cargo run -p gpui --example list_bottom_scrollbar_bug
//!
//! The list starts pinned to the bottom. Before the fix, the red scrollbar
//! thumb was pushed off the bottom of the track (invisible).
use gpui::{
App, Bounds, Context, ListAlignment, ListState, Window, WindowBounds, WindowOptions, div, list,
prelude::*, px, rgb, size,
};
use gpui_platform::application;
const ITEM_COUNT: usize = 40;
const COLORS: [u32; 4] = [0xE8F0FE, 0xFCE8E6, 0xE6F4EA, 0xFEF7E0];
struct BugRepro {
list_state: ListState,
}
impl BugRepro {
fn new() -> Self {
let list_state = ListState::new(ITEM_COUNT, ListAlignment::Bottom, px(5000.));
Self { list_state }
}
}
impl Render for BugRepro {
fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement {
let state = &self.list_state;
let max_offset = state.max_offset_for_scrollbar().y;
let raw_offset = -state.scroll_px_offset_for_scrollbar().y;
let viewport_h = state.viewport_bounds().size.height;
let content_h = max_offset + viewport_h;
let thumb_h = if content_h > px(0.) {
((viewport_h / content_h) * viewport_h).max(px(20.))
} else {
viewport_h
};
let thumb_top = if max_offset > px(0.) {
(raw_offset / max_offset) * (viewport_h - thumb_h)
} else {
px(0.)
};
div()
.size_full()
.flex()
.flex_row()
.bg(rgb(0xffffff))
.text_color(rgb(0x333333))
.text_xl()
.child(
div().flex_1().h_full().child(
list(state.clone(), |ix, _window, _cx| {
let height = if ix % 4 == 0 { px(70.) } else { px(40.) };
let bg = COLORS[ix % COLORS.len()];
div()
.h(height)
.w_full()
.bg(rgb(bg))
.border_b_1()
.border_color(rgb(0xcccccc))
.px_2()
.flex()
.items_center()
.child(format!("Item {ix}"))
.into_any()
})
.h_full()
.w_full(),
),
)
.child(
div()
.w(px(14.))
.h_full()
.bg(rgb(0xe0e0e0))
.relative()
.child(
div()
.absolute()
.right(px(0.))
.top(thumb_top)
.h(thumb_h)
.w(px(14.))
.rounded_sm()
.bg(rgb(0xff3333)),
),
)
}
}
fn main() {
application().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(400.), px(500.)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|_, cx| cx.new(|_| BugRepro::new()),
)
.unwrap();
cx.activate(true);
});
}
```
where I was able to test it out, here is a video of the new working
behavior.
https://github.com/user-attachments/assets/02e26308-da18-418b-97fc-dd52a3325dab
Release Notes:
- gpui: fixed a bug where the scollbar would disappear when using a
bottom aligned list.
---------
Co-authored-by: Mikayla Maki