feat: add scrollbar for virtualized lists
This commit is contained in:
@@ -3,8 +3,9 @@ use std::time::Duration;
|
||||
use gpui::prelude::FluentBuilder as _;
|
||||
use gpui::{
|
||||
App, AppContext as _, Bounds, Context, Entity, FontWeight, InteractiveElement as _,
|
||||
IntoElement, KeyBinding, ParentElement as _, Pixels, Render, SharedString, Styled as _,
|
||||
WeakEntity, Window, WindowBounds, WindowOptions, actions, div, px, size,
|
||||
IntoElement, KeyBinding, ListAlignment, ListState, ParentElement as _, Pixels, Render,
|
||||
SharedString, Styled as _, UniformListScrollHandle, WeakEntity, Window, WindowBounds,
|
||||
WindowOptions, actions, div, list, px, size, uniform_list,
|
||||
};
|
||||
use gpui_native_core::alert::{Alert, AlertSeverity, Alerts, AlertsView};
|
||||
use gpui_native_core::avatar::Avatar;
|
||||
@@ -25,6 +26,7 @@ use gpui_native_core::popover::Popover;
|
||||
use gpui_native_core::progress::Progress;
|
||||
use gpui_native_core::radio::{Radio, RadioGroup};
|
||||
use gpui_native_core::scroll_area::{ScrollArea, ScrollAxes};
|
||||
use gpui_native_core::scrollbar::{Scrollbar, ScrollbarVisibility};
|
||||
use gpui_native_core::segmented::{Segmented, SegmentedOption};
|
||||
use gpui_native_core::select::{Select, SelectOption};
|
||||
use gpui_native_core::slider::Slider;
|
||||
@@ -93,6 +95,7 @@ const CATALOG: &[(&str, &[(&str, &str)])] = &[
|
||||
("tooltip", "Tooltip"),
|
||||
("empty-state", "Empty state"),
|
||||
("scroll-area", "Scroll area"),
|
||||
("scrollbar", "Scrollbar"),
|
||||
],
|
||||
),
|
||||
(
|
||||
@@ -614,6 +617,12 @@ impl Gallery {
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
dock.register_panel(
|
||||
PanelDescriptor::new("scrollbar", "Scrollbar", |_, cx| {
|
||||
cx.new(|_| ScrollbarDemo::new()).into()
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
dock.register_panel(
|
||||
PanelDescriptor::new("sidebar", "Sidebar", |_, cx| {
|
||||
cx.new(|_| SidebarDemo { selected: None }).into()
|
||||
@@ -2614,6 +2623,119 @@ impl Render for ScrollAreaDemo {
|
||||
}
|
||||
}
|
||||
|
||||
/// The virtualized lists a [Scrollbar] drives: gpui's `uniform_list` and
|
||||
/// `list`, whose handles the overlay reads and writes.
|
||||
struct ScrollbarDemo {
|
||||
uniform: UniformListScrollHandle,
|
||||
list: ListState,
|
||||
visibility: ScrollbarVisibility,
|
||||
}
|
||||
|
||||
impl ScrollbarDemo {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
uniform: UniformListScrollHandle::new(),
|
||||
list: ListState::new(64, ListAlignment::Top, px(400.)),
|
||||
visibility: ScrollbarVisibility::Platform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ScrollbarDemo {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let theme = cx.theme();
|
||||
let colors = theme.colors;
|
||||
let radius = theme.radius;
|
||||
let list_state = self.list.clone();
|
||||
let visibility = self.visibility;
|
||||
let view = cx.entity();
|
||||
|
||||
ScrollArea::new("scrollbar-demo").size_full().p_4().child(
|
||||
v_flex()
|
||||
.gap_3()
|
||||
.child(demo_section(
|
||||
"visibility",
|
||||
colors,
|
||||
Segmented::new("scrollbar-demo-visibility", visibility)
|
||||
.options(vec![
|
||||
(ScrollbarVisibility::Platform, "Platform"),
|
||||
(ScrollbarVisibility::Always, "Always"),
|
||||
(ScrollbarVisibility::Autohide, "Autohide"),
|
||||
])
|
||||
.on_change(move |next, _, cx| {
|
||||
view.update(cx, |demo, cx| {
|
||||
demo.visibility = next;
|
||||
cx.notify();
|
||||
});
|
||||
}),
|
||||
))
|
||||
.child(demo_section(
|
||||
"uniform_list",
|
||||
colors,
|
||||
div()
|
||||
.relative()
|
||||
.h(px(240.))
|
||||
.rounded(radius.control)
|
||||
.border_1()
|
||||
.border_color(colors.border)
|
||||
.overflow_hidden()
|
||||
.child(
|
||||
uniform_list("scrollbar-demo-uniform", 120, move |range, _, _| {
|
||||
range
|
||||
.map(|row| {
|
||||
div()
|
||||
.h(px(24.))
|
||||
.px_3()
|
||||
.flex()
|
||||
.items_center()
|
||||
.border_b_1()
|
||||
.border_color(colors.border)
|
||||
.child(format!("Row {row} of 120"))
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.track_scroll(&self.uniform)
|
||||
.h_full()
|
||||
.w_full(),
|
||||
)
|
||||
.child(Scrollbar::vertical(self.uniform.clone()).visibility(visibility)),
|
||||
))
|
||||
.child(demo_section(
|
||||
"list",
|
||||
colors,
|
||||
div()
|
||||
.relative()
|
||||
.h(px(240.))
|
||||
.rounded(radius.control)
|
||||
.border_1()
|
||||
.border_color(colors.border)
|
||||
.overflow_hidden()
|
||||
.child(
|
||||
list(list_state, move |row, _, _| {
|
||||
div()
|
||||
.px_3()
|
||||
.py_1()
|
||||
.border_b_1()
|
||||
.border_color(colors.border)
|
||||
.child(format!("Item {row} — {} lines tall", 1 + row % 3))
|
||||
.h(px(28. + (row % 3) as f32 * 12.))
|
||||
.into_any_element()
|
||||
})
|
||||
.h_full()
|
||||
.w_full(),
|
||||
)
|
||||
.child(Scrollbar::vertical(self.list.clone()).visibility(visibility)),
|
||||
))
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(colors.muted_foreground)
|
||||
.child("Platform follows the running OS; scroll or grab the rail to reveal an autohidden thumb."),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct SidebarDemo {
|
||||
selected: Option<usize>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user