settings ui: Add some light design tweaks (#38934)

Release Notes:

- N/A
This commit is contained in:
Danilo Leal
2025-09-26 05:22:57 +00:00
committed by GitHub
parent ee357e8987
commit b1528601cc
+81 -73
View File
@@ -4,8 +4,8 @@ use editor::Editor;
use feature_flags::{FeatureFlag, FeatureFlagAppExt as _};
use gpui::{
App, AppContext as _, Context, Div, Entity, Global, IntoElement, ReadGlobal as _, Render,
UniformListScrollHandle, Window, WindowHandle, WindowOptions, actions, div, px, size,
uniform_list,
TitlebarOptions, UniformListScrollHandle, Window, WindowHandle, WindowOptions, actions, div,
point, px, size, uniform_list,
};
use project::WorktreeId;
use settings::{CursorShape, SaturatingBool, SettingsContent, SettingsStore};
@@ -17,12 +17,7 @@ use std::{
rc::Rc,
sync::Arc,
};
use ui::{
ActiveTheme as _, AnyElement, BorrowAppContext as _, Button, Clickable as _, Color, Divider,
DropdownMenu, FluentBuilder as _, Icon, IconName, InteractiveElement as _, Label,
LabelCommon as _, LabelSize, ListItem, ParentElement, SharedString,
StatefulInteractiveElement as _, Styled, StyledTypography, Switch, h_flex, v_flex,
};
use ui::{Divider, DropdownMenu, ListItem, Switch, prelude::*};
use util::{paths::PathStyle, rel_path::RelPath};
use crate::components::SettingsEditor;
@@ -292,11 +287,16 @@ fn init_renderers(cx: &mut App) {
pub fn open_settings_editor(cx: &mut App) -> anyhow::Result<WindowHandle<SettingsWindow>> {
cx.open_window(
WindowOptions {
titlebar: None,
titlebar: Some(TitlebarOptions {
title: Some("Settings Window".into()),
appears_transparent: true,
traffic_light_position: Some(point(px(12.0), px(12.0))),
}),
focus: true,
show: true,
kind: gpui::WindowKind::Normal,
window_min_size: Some(size(px(300.), px(500.))), // todo(settings_ui): Does this min_size make sense?
window_background: cx.theme().window_background_appearance(),
window_min_size: Some(size(px(800.), px(600.))), // 4:3 Aspect Ratio
..Default::default()
},
|window, cx| cx.new(|cx| SettingsWindow::new(window, cx)),
@@ -342,40 +342,40 @@ enum SettingsPageItem {
impl SettingsPageItem {
fn render(&self, _file: SettingsFile, window: &mut Window, cx: &mut App) -> AnyElement {
match self {
SettingsPageItem::SectionHeader(header) => div()
SettingsPageItem::SectionHeader(header) => v_flex()
.w_full()
.gap_0p5()
.child(Label::new(SharedString::new_static(header)).size(LabelSize::Large))
.child(Divider::horizontal().color(ui::DividerColor::BorderVariant))
.into_any_element(),
SettingsPageItem::SettingItem(setting_item) => {
let renderer = cx.default_global::<SettingFieldRenderer>().clone();
div()
h_flex()
.id(setting_item.title)
.w_full()
.gap_2()
.flex_wrap()
.justify_between()
.child(
Label::new(SharedString::new_static(setting_item.title))
.size(LabelSize::Default),
)
.child(
h_flex()
.justify_between()
v_flex()
.max_w_1_2()
.flex_shrink()
.child(
div()
.child(
Label::new(SharedString::new_static(
setting_item.description,
))
.size(LabelSize::Small)
.color(Color::Muted),
)
.max_w_1_2(),
Label::new(SharedString::new_static(setting_item.title))
.size(LabelSize::Default),
)
.child(renderer.render(
setting_item.field.as_ref(),
setting_item.metadata.as_deref(),
window,
cx,
)),
.child(
Label::new(SharedString::new_static(setting_item.description))
.size(LabelSize::Small)
.color(Color::Muted),
),
)
.child(renderer.render(
setting_item.field.as_ref(),
setting_item.metadata.as_deref(),
window,
cx,
))
.into_any_element()
}
}
@@ -423,7 +423,7 @@ impl SettingsWindow {
let current_file = SettingsFile::User;
let search = cx.new(|cx| {
let mut editor = Editor::single_line(window, cx);
editor.set_placeholder_text("Search Settings", window, cx);
editor.set_placeholder_text("Search settings", window, cx);
editor
});
let mut this = Self {
@@ -526,9 +526,7 @@ impl SettingsWindow {
}
fn render_files(&self, _window: &mut Window, cx: &mut Context<SettingsWindow>) -> Div {
div()
.flex()
.flex_row()
h_flex()
.gap_1()
.children(self.files.iter().enumerate().map(|(ix, file)| {
Button::new(ix, file.name())
@@ -536,19 +534,30 @@ impl SettingsWindow {
}))
}
fn render_search(&self, _window: &mut Window, _cx: &mut App) -> Div {
fn render_search(&self, _window: &mut Window, cx: &mut App) -> Div {
h_flex()
.child(Icon::new(IconName::MagnifyingGlass))
.pt_1()
.px_1p5()
.gap_1p5()
.rounded_sm()
.bg(cx.theme().colors().editor_background)
.border_1()
.border_color(cx.theme().colors().border)
.child(Icon::new(IconName::MagnifyingGlass).color(Color::Muted))
.child(self.search.clone())
}
fn render_nav(&self, window: &mut Window, cx: &mut Context<SettingsWindow>) -> Div {
v_flex()
.bg(cx.theme().colors().panel_background)
.p_3()
.child(div().h_10()) // Files spacer;
.child(self.render_search(window, cx).pb_1())
.w_64()
.p_2p5()
.pt_10()
.gap_3()
.flex_none()
.border_r_1()
.border_color(cx.theme().colors().border)
.bg(cx.theme().colors().panel_background)
.child(self.render_search(window, cx).pb_1())
.child(
uniform_list(
"settings-ui-nav-bar",
@@ -559,12 +568,25 @@ impl SettingsWindow {
.map(|ix| {
let entry = &this.navbar_entries[ix];
div()
h_flex()
.id(("settings-ui-section", ix))
.w_full()
.pl_2p5()
.py_0p5()
.rounded_sm()
.border_1()
.border_color(cx.theme().colors().border_transparent)
.text_color(cx.theme().colors().text_muted)
.when(this.is_navbar_entry_selected(ix), |this| {
this.text_color(cx.theme().colors().text)
.bg(cx.theme().colors().element_selected.opacity(0.2))
.border_color(cx.theme().colors().border)
})
.child(
ListItem::new(("settings-ui-navbar-entry", ix))
.selectable(true)
.indent_step_size(px(10.))
.inset(true)
.indent_step_size(px(1.))
.indent_level(if entry.is_root { 1 } else { 3 })
.when(entry.is_root, |item| {
item.toggle(
@@ -579,26 +601,13 @@ impl SettingsWindow {
}))
})
.child(
div()
h_flex()
.text_ui(cx)
.size_full()
.child(entry.title)
.hover(|style| {
style.bg(cx.theme().colors().element_hover)
.truncate()
.hover(|s| {
s.bg(cx.theme().colors().element_hover)
})
.when(!entry.is_root, |this| {
this.text_color(
cx.theme().colors().text_muted,
)
})
.when(
this.is_navbar_entry_selected(ix),
|this| {
this.text_color(
Color::Selected.color(cx),
)
},
),
.child(entry.title),
),
)
.on_click(cx.listener(move |this, _, _, cx| {
@@ -610,7 +619,6 @@ impl SettingsWindow {
}),
)
.track_scroll(self.list_handle.clone())
.gap_1_5()
.size_full()
.flex_grow(),
)
@@ -622,7 +630,7 @@ impl SettingsWindow {
window: &mut Window,
cx: &mut Context<SettingsWindow>,
) -> Div {
v_flex().gap_4().py_4().children(
v_flex().gap_4().children(
page.items
.iter()
.map(|item| item.render(self.current_file.clone(), window, cx)),
@@ -655,21 +663,21 @@ impl SettingsWindow {
impl Render for SettingsWindow {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.bg(cx.theme().colors().background)
.flex()
.flex_row()
.size_full()
.bg(cx.theme().colors().background)
.text_color(cx.theme().colors().text)
.child(self.render_nav(window, cx).w(px(300.0)))
.child(Divider::vertical().color(ui::DividerColor::BorderVariant))
.child(self.render_nav(window, cx))
.child(
v_flex()
.bg(cx.theme().colors().editor_background)
.w_full()
.pt_4()
.px_6()
.py_2()
.gap_4()
.bg(cx.theme().colors().editor_background)
.child(self.render_files(window, cx))
.child(self.render_page(self.current_page(), window, cx))
.w_full(),
.child(self.render_page(self.current_page(), window, cx)),
)
}
}