Components / Data
Virtualized list
Markdown crates/ui/src/list.rs docs.rs
use ui::{list, scroll};
div().relative().h(px(240.0))
.child(list::virtual_list("rows", rows.len(), px(28.0), &self.rows_scroll, {
let rows = rows.clone();
move |range, _, _| range.map(|ix| row(&rows[ix])).collect()
}))
.child(scroll::scrollbar(
"rows-bar",
&list::scroll_handle(&self.rows_scroll),
&self.rows_bar,
))Thin on purpose — gpui already does the hard part.
API
// ui::list
/// `uniform_list` measures the *first* row and lays every other out at that
/// height; hand it uneven rows and nothing errors, the content just overlaps.
/// This applies `row_height` to every row it returns.
pub fn virtual_list<R: IntoElement>(
id: impl Into<ElementId>,
count: usize,
row_height: Pixels,
handle: &UniformListScrollHandle,
render: impl 'static + Fn(Range<usize>, &mut Window, &mut App) -> Vec<R>,
) -> UniformList;
/// The reach to the real `ScrollHandle` inside a `UniformListScrollHandle`,
/// named so a consumer does not have to find it in gpui's source. The clone
/// shares state.
pub fn scroll_handle(handle: &UniformListScrollHandle) -> ScrollHandle;
// ...The list fills its parent: one with no height of its own collapses to a single measured row and then nothing. Set your own size after the call — the later call wins.
gpui's other virtualizer, list(), takes rows of varying height and cannot carry a proportional scrollbar: a thumb's length is the visible share of a total height, and a variable-height list cannot know its total without measuring every row.