@@ -131,7 +131,7 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
SettingsPageItem::SettingItem(SettingItem {
files: USER,
title: "Settings Profiles",
- description: "Any number of settings profiles that are temporarily applied on top of your existing user settings.",
+ description: "Any number of settings profiles that are temporarily applied on top of your existing user settings",
field: Box::new(
SettingField {
pick: |settings_content| &settings_content.workspace.use_system_prompts,
@@ -295,6 +295,28 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
metadata: None,
files: USER,
}),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Agent Panel UI Font Size",
+ description: "Font size for agent response text in the agent panel. Falls back to the regular UI font size.",
+ field: Box::new(SettingField {
+ pick: |settings_content| &settings_content.theme.agent_ui_font_size,
+ pick_mut: |settings_content| &mut settings_content.theme.agent_ui_font_size,
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Agent Panel Buffer Font Size",
+ description: "Font size for user messages text in the agent panel",
+ field: Box::new(SettingField {
+ pick: |settings_content| &settings_content.theme.agent_buffer_font_size,
+ pick_mut: |settings_content| {
+ &mut settings_content.theme.agent_buffer_font_size
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
SettingsPageItem::SectionHeader("Keymap"),
SettingsPageItem::SettingItem(SettingItem {
title: "Base Keymap",
@@ -1020,7 +1042,7 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Min Line Number Digits",
- description: "Minimum number of characters to reserve space for in the gutter.",
+ description: "Minimum number of characters to reserve space for in the gutter",
field: Box::new(SettingField {
pick: |settings_content| {
if let Some(gutter) = &settings_content.editor.gutter {
@@ -1638,6 +1660,27 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
title: "Workbench & Window",
items: vec![
SettingsPageItem::SectionHeader("Status Bar"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Project Panel Button",
+ description: "Whether to show the project panel button in the status bar",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(project_panel) = &settings_content.project_panel {
+ &project_panel.button
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .project_panel
+ .get_or_insert_default()
+ .button
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
SettingsPageItem::SettingItem(SettingItem {
title: "Active Language Button",
description: "Whether to show the active language button in the status bar",
@@ -1738,6 +1781,24 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
metadata: None,
files: USER,
}),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Debugger Button",
+ description: "Whether to show the debugger button in the status bar",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(debugger) = &settings_content.debugger {
+ &debugger.button
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content.debugger.get_or_insert_default().button
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
SettingsPageItem::SectionHeader("Tab Bar"),
SettingsPageItem::SettingItem(SettingItem {
title: "Editor Tabs",
@@ -1844,7 +1905,7 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Show Onboarding Banner",
- description: "Whether to show onboarding banners in the titlebar",
+ description: "Whether to show banners announcing new features in the titlebar",
field: Box::new(SettingField {
pick: |settings_content| {
if let Some(title_bar) = &settings_content.title_bar {
@@ -2255,27 +2316,6 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
title: "Panels",
items: vec![
SettingsPageItem::SectionHeader("Project Panel"),
- SettingsPageItem::SettingItem(SettingItem {
- title: "Project Panel Button",
- description: "Whether to show the project panel button in the status bar",
- field: Box::new(SettingField {
- pick: |settings_content| {
- if let Some(project_panel) = &settings_content.project_panel {
- &project_panel.button
- } else {
- &None
- }
- },
- pick_mut: |settings_content| {
- &mut settings_content
- .project_panel
- .get_or_insert_default()
- .button
- },
- }),
- metadata: None,
- files: USER,
- }),
SettingsPageItem::SettingItem(SettingItem {
title: "Project Panel Dock",
description: "Where to dock the project panel",
@@ -2884,8 +2924,8 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
}),
SettingsPageItem::SectionHeader("Git Panel"),
SettingsPageItem::SettingItem(SettingItem {
- title: "Button",
- description: "Whether to show the git panel button in the status bar",
+ title: "Git Panel Button",
+ description: "Whether to show the Git panel button in the status bar",
field: Box::new(SettingField {
pick: |settings_content| {
if let Some(git_panel) = &settings_content.git_panel {
@@ -2902,8 +2942,8 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
- title: "Dock",
- description: "Where to dock the git panel",
+ title: "Git Panel Dock",
+ description: "Where to dock the Git panel",
field: Box::new(SettingField {
pick: |settings_content| {
if let Some(git_panel) = &settings_content.git_panel {
@@ -2920,8 +2960,8 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
- title: "Default Width",
- description: "Default width of the git panel in pixels",
+ title: "Git Panel Default Width",
+ description: "Default width of the Git panel in pixels",
field: Box::new(SettingField {
pick: |settings_content| {
if let Some(git_panel) = &settings_content.git_panel {
@@ -2940,6 +2980,25 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
metadata: None,
files: USER,
}),
+ SettingsPageItem::SectionHeader("Debugger Panel"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Debugger Panel Dock",
+ description: "The dock position of the debug panel",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(debugger) = &settings_content.debugger {
+ &debugger.dock
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content.debugger.get_or_insert_default().dock
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
SettingsPageItem::SectionHeader("Notification Panel"),
SettingsPageItem::SettingItem(SettingItem {
title: "Notification Panel Button",
@@ -3636,24 +3695,6 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
metadata: None,
files: USER,
}),
- SettingsPageItem::SettingItem(SettingItem {
- title: "Dock",
- description: "The dock position of the debug panel",
- field: Box::new(SettingField {
- pick: |settings_content| {
- if let Some(debugger) = &settings_content.debugger {
- &debugger.dock
- } else {
- &None
- }
- },
- pick_mut: |settings_content| {
- &mut settings_content.debugger.get_or_insert_default().dock
- },
- }),
- metadata: None,
- files: USER,
- }),
SettingsPageItem::SettingItem(SettingItem {
title: "Log DAP Communications",
description: "Whether to log messages between active debug adapters and Zed",
@@ -3696,24 +3737,6 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
metadata: None,
files: USER,
}),
- SettingsPageItem::SettingItem(SettingItem {
- title: "Button",
- description: "Whether to show the debug button in the status bar",
- field: Box::new(SettingField {
- pick: |settings_content| {
- if let Some(debugger) = &settings_content.debugger {
- &debugger.button
- } else {
- &None
- }
- },
- pick_mut: |settings_content| {
- &mut settings_content.debugger.get_or_insert_default().button
- },
- }),
- metadata: None,
- files: USER,
- }),
],
},
SettingsPage {
@@ -4006,7 +4029,7 @@ fn language_settings_data() -> Vec<SettingsPageItem> {
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Show Wrap Guides",
- description: "Whether to show wrap guides in the editor. Setting this to true will show a guide at the 'preferred_line_length' value if softwrap is set to 'preferred_line_length', and will show any additional guides as specified by the 'wrap_guides' setting",
+ description: "Whether to show wrap guides in the editor",
field: Box::new(SettingField {
pick: |settings_content| {
language_settings_field(settings_content, |language| &language.show_wrap_guides)
@@ -4438,7 +4461,7 @@ fn language_settings_data() -> Vec<SettingsPageItem> {
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Always Treat Brackets As Autoclosed",
- description: "Controls how the editor handles the autoclosed characters. When set to `false`(default), skipping over and auto-removing of the closing characters happen only for auto-inserted characters. Otherwise(when `true`), the closing characters are always skipped over and auto-removed no matter how they were inserted",
+ description: "Controls whether the closing characters are always skipped over and auto-removed no matter how they were inserted",
field: Box::new(SettingField {
pick: |settings_content| {
language_settings_field(settings_content, |language| {
@@ -4518,7 +4541,7 @@ fn language_settings_data() -> Vec<SettingsPageItem> {
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Linked Edits",
- description: "Whether to perform linked edits of associated ranges, if the language server supports it. For example, when editing opening <html> tag, the contents of the closing </html> tag will be edited as well",
+ description: "Whether to perform linked edits of associated ranges, if the LS supports it. For example, when editing opening <html> tag, the contents of the closing </html> tag will be edited as well",
field: Box::new(SettingField {
pick: |settings_content| {
language_settings_field(settings_content, |language| &language.linked_edits)
@@ -29,8 +29,9 @@ use std::{
sync::{Arc, LazyLock, RwLock, atomic::AtomicBool},
};
use ui::{
- ContextMenu, Divider, DropdownMenu, DropdownStyle, IconButtonShape, KeyBinding, KeybindingHint,
- PopoverMenu, Switch, SwitchColor, TreeViewItem, WithScrollbar, prelude::*,
+ ContextMenu, Divider, DividerColor, DropdownMenu, DropdownStyle, IconButtonShape, KeyBinding,
+ KeybindingHint, PopoverMenu, Switch, SwitchColor, Tooltip, TreeViewItem, WithScrollbar,
+ prelude::*,
};
use ui_input::{NumberField, NumberFieldType};
use util::{ResultExt as _, paths::PathStyle, rel_path::RelPath};
@@ -242,6 +243,9 @@ fn init_renderers(cx: &mut App) {
.icon_color(Color::Error)
.icon_size(IconSize::Small)
.style(ButtonStyle::Outlined)
+ .tooltip(Tooltip::text(
+ "This warning is only displayed in dev builds.",
+ ))
.into_any_element()
})
.add_renderer::<bool>(|settings_field, file, _, _, cx| {
@@ -554,14 +558,14 @@ impl SettingsPageItem {
match self {
SettingsPageItem::SectionHeader(header) => v_flex()
.w_full()
- .gap_1()
+ .gap_1p5()
.child(
Label::new(SharedString::new_static(header))
- .size(LabelSize::XSmall)
+ .size(LabelSize::Small)
.color(Color::Muted)
.buffer_font(cx),
)
- .child(Divider::horizontal().color(ui::DividerColor::BorderVariant))
+ .child(Divider::horizontal().color(DividerColor::BorderFaded))
.into_any_element(),
SettingsPageItem::SettingItem(setting_item) => {
let renderer = cx.default_global::<SettingFieldRenderer>().clone();
@@ -571,8 +575,8 @@ impl SettingsPageItem {
h_flex()
.id(setting_item.title)
.w_full()
+ .min_w_0()
.gap_2()
- .flex_wrap()
.justify_between()
.map(|this| {
if is_last {
@@ -585,8 +589,8 @@ impl SettingsPageItem {
})
.child(
v_flex()
+ .w_full()
.max_w_1_2()
- .flex_shrink()
.child(
h_flex()
.w_full()
@@ -620,6 +624,9 @@ impl SettingsPageItem {
.icon_color(Color::Error)
.icon_size(IconSize::Small)
.style(ButtonStyle::Outlined)
+ .tooltip(Tooltip::text(
+ "This warning is only displayed in dev builds.",
+ ))
.into_any_element()
} else {
renderer.render(
@@ -651,7 +658,6 @@ impl SettingsPageItem {
)
.child(
Button::new(("sub-page".into(), sub_page_link.title), "Configure")
- .size(ButtonSize::Medium)
.icon(IconName::ChevronRight)
.icon_position(IconPosition::End)
.icon_color(Color::Muted)
@@ -1218,6 +1224,7 @@ impl SettingsWindow {
h_flex()
.py_1()
.px_1p5()
+ .mb_3()
.gap_1p5()
.rounded_sm()
.bg(cx.theme().colors().editor_background)
@@ -1233,7 +1240,7 @@ impl SettingsWindow {
cx: &mut Context<SettingsWindow>,
) -> impl IntoElement {
let visible_count = self.visible_navbar_entries().count();
- let nav_background = cx.theme().colors().panel_background;
+
let focus_keybind_label = if self.navbar_focus_handle.contains_focused(window, cx) {
"Focus Content"
} else {
@@ -1244,15 +1251,14 @@ impl SettingsWindow {
.w_64()
.p_2p5()
.pt_10()
- .gap_3()
.flex_none()
.border_r_1()
.border_color(cx.theme().colors().border)
- .bg(nav_background)
+ .bg(cx.theme().colors().panel_background)
.child(self.render_search(window, cx))
.child(
v_flex()
- .flex_grow()
+ .size_full()
.track_focus(&self.navbar_focus_handle)
.tab_group()
.tab_index(NAVBAR_GROUP_TAB_INDEX)
@@ -1280,53 +1286,46 @@ impl SettingsWindow {
},
))
})
- .on_click(cx.listener(
- move |this, evt: &gpui::ClickEvent, window, cx| {
- this.navbar_entry = ix;
-
- if !this.navbar_entries[ix].is_root {
- let mut selected_page_ix = ix;
-
- while !this.navbar_entries[selected_page_ix]
- .is_root
- {
- selected_page_ix -= 1;
- }
-
- let section_header = ix - selected_page_ix;
-
- if let Some(section_index) = this
- .page_items()
- .enumerate()
- .filter(|item| {
- matches!(
- item.1,
- SettingsPageItem::SectionHeader(_)
- )
- })
- .take(section_header)
- .last()
- .map(|pair| pair.0)
- {
- this.scroll_handle
- .scroll_to_top_of_item(section_index);
- }
+ .on_click(cx.listener(move |this, _, _, cx| {
+ this.navbar_entry = ix;
+
+ if !this.navbar_entries[ix].is_root {
+ let mut selected_page_ix = ix;
+
+ while !this.navbar_entries[selected_page_ix].is_root
+ {
+ selected_page_ix -= 1;
}
- if evt.is_keyboard() {
- // todo(settings_ui): Focus the actual item and scroll to it
- this.focus_first_content_item(window, cx);
+ let section_header = ix - selected_page_ix;
+
+ if let Some(section_index) = this
+ .page_items()
+ .enumerate()
+ .filter(|item| {
+ matches!(
+ item.1,
+ SettingsPageItem::SectionHeader(_)
+ )
+ })
+ .take(section_header)
+ .last()
+ .map(|pair| pair.0)
+ {
+ this.scroll_handle
+ .scroll_to_top_of_item(section_index);
}
- cx.notify();
- },
- ))
+ }
+
+ cx.notify();
+ }))
.into_any_element()
})
.collect()
}),
)
- .track_scroll(self.list_handle.clone())
- .flex_grow(),
+ .size_full()
+ .track_scroll(self.list_handle.clone()),
)
.vertical_scrollbar_for(self.list_handle.clone(), window, cx),
)
@@ -1335,6 +1334,7 @@ impl SettingsWindow {
.w_full()
.p_2()
.pb_0p5()
+ .flex_none()
.border_t_1()
.border_color(cx.theme().colors().border_variant)
.children(
@@ -1804,7 +1804,6 @@ fn render_number_field<T: NumberFieldType + Send + Sync>(
.log_err(); // todo(settings_ui) don't log err
}
})
- .tab_index(0)
.into_any_element()
}
@@ -6,7 +6,7 @@ use std::{
};
use editor::{Editor, EditorStyle};
-use gpui::{ClickEvent, Entity, FocusHandle, Focusable, FontWeight, Modifiers};
+use gpui::{ClickEvent, CursorStyle, Entity, FocusHandle, Focusable, FontWeight, Modifiers};
use settings::{CodeFade, MinimumContrast};
use ui::prelude::*;
@@ -344,6 +344,27 @@ impl<T: NumberFieldType> RenderOnce for NumberField<T> {
}
};
+ let bg_color = cx.theme().colors().surface_background;
+ let hover_bg_color = cx.theme().colors().element_hover;
+
+ let border_color = cx.theme().colors().border_variant;
+ let focus_border_color = cx.theme().colors().border_focused;
+
+ let base_button = |icon: IconName| {
+ h_flex()
+ .cursor(CursorStyle::PointingHand)
+ .p_1p5()
+ .size_full()
+ .justify_center()
+ .overflow_hidden()
+ .border_1()
+ .border_color(border_color)
+ .bg(bg_color)
+ .hover(|s| s.bg(hover_bg_color))
+ .focus(|s| s.border_color(focus_border_color).bg(hover_bg_color))
+ .child(Icon::new(icon).size(IconSize::Small))
+ };
+
h_flex()
.id(self.id.clone())
.track_focus(&self.focus_handle)
@@ -376,28 +397,19 @@ impl<T: NumberFieldType> RenderOnce for NumberField<T> {
};
decrement.child(
- h_flex()
+ base_button(IconName::Dash)
.id("decrement_button")
- .cursor(gpui::CursorStyle::PointingHand)
- .p_1p5()
- .size_full()
- .justify_center()
- .overflow_hidden()
.rounded_tl_sm()
.rounded_bl_sm()
- .border_1()
- .border_color(cx.theme().colors().border_variant)
- .bg(cx.theme().colors().surface_background)
- .hover(|s| s.bg(cx.theme().colors().element_hover))
- .child(Icon::new(IconName::Dash).size(IconSize::Small))
- .when_some(tab_index.as_mut(), |this, tab_index| {
- *tab_index += 1;
- this.tab_index(*tab_index - 1).focus(|style| {
- style
- .border_color(cx.theme().colors().border_focused)
- .bg(cx.theme().colors().element_hover)
- })
- })
+ .tab_index(
+ tab_index
+ .as_mut()
+ .map(|tab_index| {
+ *tab_index += 1;
+ *tab_index - 1
+ })
+ .unwrap_or(0),
+ )
.on_click(decrement_handler),
)
})
@@ -406,34 +418,23 @@ impl<T: NumberFieldType> RenderOnce for NumberField<T> {
.min_w_16()
.size_full()
.border_y_1()
- .border_color(cx.theme().colors().border_variant)
- .bg(cx.theme().colors().surface_background)
- .in_focus(|this| this.border_color(cx.theme().colors().border_focused))
+ .border_color(border_color)
+ .bg(bg_color)
+ .in_focus(|this| this.border_color(focus_border_color))
.child(match *self.mode.read(cx) {
NumberFieldMode::Read => h_flex()
- .id("numeric_stepper_label")
.px_1()
.flex_1()
.justify_center()
.child(Label::new((self.format)(&self.value)))
- .when_some(tab_index.as_mut(), |this, tab_index| {
- *tab_index += 1;
- this.tab_index(*tab_index - 1).focus(|style| {
- style
- .border_color(cx.theme().colors().border_focused)
- .bg(cx.theme().colors().element_hover)
- })
- })
- .on_click({
- let _mode = self.mode.clone();
- move |click, _, _cx| {
- if click.click_count() == 2 || click.is_keyboard() {
- // Edit mode is disabled until we implement center text alignment for editor
- // mode.write(cx, NumberFieldMode::Edit);
- }
- }
- })
.into_any_element(),
+ // Edit mode is disabled until we implement center text alignment for editor
+ // mode.write(cx, NumberFieldMode::Edit);
+ //
+ // When we get to making Edit mode work, we shouldn't even focus the decrement/increment buttons.
+ // Focus should go instead straight to the editor, avoiding any double-step focus.
+ // In this world, the buttons become a mouse-only interaction, given users should be able
+ // to do everything they'd do with the buttons straight in the editor anyway.
NumberFieldMode::Edit => h_flex()
.flex_1()
.child(window.use_state(cx, {
@@ -501,28 +502,19 @@ impl<T: NumberFieldType> RenderOnce for NumberField<T> {
};
increment.child(
- h_flex()
+ base_button(IconName::Plus)
.id("increment_button")
- .cursor(gpui::CursorStyle::PointingHand)
- .p_1p5()
- .size_full()
- .justify_center()
- .overflow_hidden()
.rounded_tr_sm()
.rounded_br_sm()
- .border_1()
- .border_color(cx.theme().colors().border_variant)
- .bg(cx.theme().colors().surface_background)
- .hover(|s| s.bg(cx.theme().colors().element_hover))
- .child(Icon::new(IconName::Plus).size(IconSize::Small))
- .when_some(tab_index.as_mut(), |this, tab_index| {
- *tab_index += 1;
- this.tab_index(*tab_index - 1).focus(|style| {
- style
- .border_color(cx.theme().colors().border_focused)
- .bg(cx.theme().colors().element_hover)
- })
- })
+ .tab_index(
+ tab_index
+ .as_mut()
+ .map(|tab_index| {
+ *tab_index += 1;
+ *tab_index - 1
+ })
+ .unwrap_or(0),
+ )
.on_click(increment_handler),
)
}),