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

Danilo Leal created

Release Notes:

- N/A

Change summary

crates/settings_ui/src/settings_ui.rs | 152 +++++++++++++++-------------
1 file changed, 80 insertions(+), 72 deletions(-)

Detailed changes

crates/settings_ui/src/settings_ui.rs 🔗

@@ -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()
+            .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)
-            .p_3()
-            .child(div().h_10()) // Files spacer;
             .child(self.render_search(window, cx).pb_1())
-            .gap_3()
             .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)),
             )
     }
 }