setting: Add scrollbar to SettingPage. (#1660)
This commit is contained in:
parent
857f7973e3
commit
fc36451a27
5 changed files with 104 additions and 76 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use gpui::{
|
||||
App, AppContext, Axis, Context, Element, Entity, FocusHandle, Focusable, Global, IntoElement,
|
||||
ParentElement as _, Render, SharedString, Styled, Window,
|
||||
ParentElement as _, Render, SharedString, Styled, Window, px,
|
||||
};
|
||||
|
||||
use gpui_component::{
|
||||
|
|
@ -99,6 +99,10 @@ impl super::Story for SettingsStory {
|
|||
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
|
||||
Self::view(window, cx)
|
||||
}
|
||||
|
||||
fn paddings() -> gpui::Pixels {
|
||||
px(0.)
|
||||
}
|
||||
}
|
||||
|
||||
impl SettingsStory {
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ impl Render for SidebarStory {
|
|||
Sidebar::new(self.side)
|
||||
.collapsed(self.collapsed)
|
||||
.w(px(220.))
|
||||
.p_3()
|
||||
.gap_0()
|
||||
.header(
|
||||
SidebarHeader::new()
|
||||
.child(
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use gpui::{
|
||||
list, prelude::FluentBuilder as _, px, App, Entity, InteractiveElement as _, IntoElement,
|
||||
ParentElement as _, SharedString, StatefulInteractiveElement, Styled, Window,
|
||||
div, list, prelude::FluentBuilder as _, px, App, Entity, InteractiveElement as _, IntoElement,
|
||||
ListAlignment, ListState, ParentElement as _, SharedString, Styled, Window,
|
||||
};
|
||||
use rust_i18n::t;
|
||||
|
||||
use crate::{
|
||||
button::{Button, ButtonVariants},
|
||||
divider::Divider,
|
||||
h_flex,
|
||||
label::Label,
|
||||
scroll::{Scrollbar, ScrollbarState},
|
||||
setting::{settings::SettingsState, RenderOptions, SettingGroup},
|
||||
v_flex, ActiveTheme, IconName, Sizable,
|
||||
};
|
||||
|
|
@ -100,11 +100,16 @@ impl SettingPage {
|
|||
.collect::<Vec<_>>();
|
||||
let groups_count = groups.len();
|
||||
|
||||
let list_state = window
|
||||
let (scroll_state, list_state) = window
|
||||
.use_keyed_state(
|
||||
SharedString::from(format!("list-state:{}", ix)),
|
||||
cx,
|
||||
|_, _| gpui::ListState::new(groups_count, gpui::ListAlignment::Top, px(0.)),
|
||||
|_, _| {
|
||||
(
|
||||
ScrollbarState::default(),
|
||||
ListState::new(groups_count, ListAlignment::Top, px(100.)),
|
||||
)
|
||||
},
|
||||
)
|
||||
.read(cx)
|
||||
.clone();
|
||||
|
|
@ -123,12 +128,13 @@ impl SettingPage {
|
|||
|
||||
v_flex()
|
||||
.id(ix)
|
||||
.p_4()
|
||||
.size_full()
|
||||
.overflow_scroll()
|
||||
.child(
|
||||
v_flex()
|
||||
.p_4()
|
||||
.gap_3()
|
||||
.border_b_1()
|
||||
.border_color(cx.theme().border)
|
||||
.child(h_flex().justify_between().child(self.title.clone()).when(
|
||||
self.is_resettable(cx),
|
||||
|this| {
|
||||
|
|
@ -153,22 +159,37 @@ impl SettingPage {
|
|||
.text_sm()
|
||||
.text_color(cx.theme().muted_foreground),
|
||||
)
|
||||
})
|
||||
.child(Divider::horizontal()),
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
list(list_state.clone(), {
|
||||
let query = query.clone();
|
||||
let options = *options;
|
||||
move |ix, window, cx| {
|
||||
let group = groups[ix].clone();
|
||||
group
|
||||
.pt_6()
|
||||
.render(ix, &query, &options, window, cx)
|
||||
.into_any_element()
|
||||
}
|
||||
})
|
||||
.size_full(),
|
||||
div()
|
||||
.px_4()
|
||||
.relative()
|
||||
.flex_1()
|
||||
.w_full()
|
||||
.child(
|
||||
list(list_state.clone(), {
|
||||
let query = query.clone();
|
||||
let options = *options;
|
||||
move |ix, window, cx| {
|
||||
let group = groups[ix].clone();
|
||||
group
|
||||
.py_4()
|
||||
.render(ix, &query, &options, window, cx)
|
||||
.into_any_element()
|
||||
}
|
||||
})
|
||||
.size_full(),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.absolute()
|
||||
.top_0()
|
||||
.left_0()
|
||||
.right_0()
|
||||
.bottom_0()
|
||||
.child(Scrollbar::vertical(&scroll_state, &list_state)),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ use crate::{
|
|||
resizable::{h_resizable, resizable_panel},
|
||||
setting::{SettingGroup, SettingPage},
|
||||
sidebar::{Sidebar, SidebarMenu, SidebarMenuItem},
|
||||
IconName, Sizable, Size,
|
||||
IconName, Sizable, Size, StyledExt,
|
||||
};
|
||||
use gpui::{
|
||||
div, prelude::FluentBuilder as _, px, relative, App, AppContext as _, Axis, ElementId, Entity,
|
||||
IntoElement, ParentElement as _, Pixels, RenderOnce, Styled, Window,
|
||||
IntoElement, ParentElement as _, Pixels, RenderOnce, StyleRefinement, Styled, Window,
|
||||
};
|
||||
use rust_i18n::t;
|
||||
|
||||
|
|
@ -31,6 +31,7 @@ pub struct Settings {
|
|||
group_variant: GroupBoxVariant,
|
||||
size: Size,
|
||||
sidebar_width: Pixels,
|
||||
sidebar_style: StyleRefinement,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
|
|
@ -42,6 +43,7 @@ impl Settings {
|
|||
group_variant: GroupBoxVariant::default(),
|
||||
size: Size::default(),
|
||||
sidebar_width: px(250.0),
|
||||
sidebar_style: StyleRefinement::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +73,12 @@ impl Settings {
|
|||
self
|
||||
}
|
||||
|
||||
/// Set the style refinement for the sidebar.
|
||||
pub fn sidebar_style(mut self, style: &StyleRefinement) -> Self {
|
||||
self.sidebar_style = style.clone();
|
||||
self
|
||||
}
|
||||
|
||||
fn filtered_pages(&self, query: &str) -> Vec<SettingPage> {
|
||||
self.pages
|
||||
.iter()
|
||||
|
|
@ -138,6 +146,7 @@ impl Settings {
|
|||
Sidebar::left()
|
||||
.w(relative(1.))
|
||||
.border_0()
|
||||
.refine_style(&self.sidebar_style)
|
||||
.collapsed(false)
|
||||
.header(
|
||||
div()
|
||||
|
|
@ -145,57 +154,52 @@ impl Settings {
|
|||
.child(Input::new(&search_input).prefix(IconName::Search)),
|
||||
)
|
||||
.child(
|
||||
SidebarMenu::new()
|
||||
.p_2()
|
||||
.children(pages.iter().enumerate().map(|(page_ix, page)| {
|
||||
let is_page_active =
|
||||
selected_index.page_ix == page_ix && selected_index.group_ix.is_none();
|
||||
SidebarMenuItem::new(page.title.clone())
|
||||
.default_open(page.default_open)
|
||||
.active(is_page_active)
|
||||
.on_click({
|
||||
let state = state.clone();
|
||||
move |_, _, cx| {
|
||||
state.update(cx, |state, cx| {
|
||||
state.selected_index = SelectIndex {
|
||||
page_ix,
|
||||
..Default::default()
|
||||
};
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
})
|
||||
.when(page.groups.len() > 1, |this| {
|
||||
this.children(
|
||||
page.groups
|
||||
.iter()
|
||||
.filter(|g| g.title.is_some())
|
||||
.enumerate()
|
||||
.map(|(group_ix, group)| {
|
||||
let is_active = selected_index.page_ix == page_ix
|
||||
&& selected_index.group_ix == Some(group_ix);
|
||||
let title = group.title.clone().unwrap_or_default();
|
||||
SidebarMenu::new().children(pages.iter().enumerate().map(|(page_ix, page)| {
|
||||
let is_page_active =
|
||||
selected_index.page_ix == page_ix && selected_index.group_ix.is_none();
|
||||
SidebarMenuItem::new(page.title.clone())
|
||||
.default_open(page.default_open)
|
||||
.active(is_page_active)
|
||||
.on_click({
|
||||
let state = state.clone();
|
||||
move |_, _, cx| {
|
||||
state.update(cx, |state, cx| {
|
||||
state.selected_index = SelectIndex {
|
||||
page_ix,
|
||||
..Default::default()
|
||||
};
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
})
|
||||
.when(page.groups.len() > 1, |this| {
|
||||
this.children(
|
||||
page.groups
|
||||
.iter()
|
||||
.filter(|g| g.title.is_some())
|
||||
.enumerate()
|
||||
.map(|(group_ix, group)| {
|
||||
let is_active = selected_index.page_ix == page_ix
|
||||
&& selected_index.group_ix == Some(group_ix);
|
||||
let title = group.title.clone().unwrap_or_default();
|
||||
|
||||
SidebarMenuItem::new(title).active(is_active).on_click(
|
||||
{
|
||||
let state = state.clone();
|
||||
move |_, _, cx| {
|
||||
state.update(cx, |state, cx| {
|
||||
state.selected_index = SelectIndex {
|
||||
page_ix,
|
||||
group_ix: Some(group_ix),
|
||||
};
|
||||
state.deferred_scroll_group_ix =
|
||||
Some(group_ix);
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
}),
|
||||
)
|
||||
})
|
||||
})),
|
||||
SidebarMenuItem::new(title).active(is_active).on_click({
|
||||
let state = state.clone();
|
||||
move |_, _, cx| {
|
||||
state.update(cx, |state, cx| {
|
||||
state.selected_index = SelectIndex {
|
||||
page_ix,
|
||||
group_ix: Some(group_ix),
|
||||
};
|
||||
state.deferred_scroll_group_ix = Some(group_ix);
|
||||
cx.notify();
|
||||
})
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
})
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ impl<E: Collapsible + IntoElement> RenderOnce for Sidebar<E> {
|
|||
.w(DEFAULT_WIDTH)
|
||||
.flex_shrink_0()
|
||||
.h_full()
|
||||
.gap_3()
|
||||
.overflow_hidden()
|
||||
.relative()
|
||||
.bg(cx.theme().sidebar)
|
||||
|
|
|
|||
Loading…
Reference in a new issue