From 176a68f90f6d14dd67e6ac3e34b9d3d55c6d56fa Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 20 Nov 2023 10:46:23 -0500 Subject: [PATCH 1/6] kb --- assets/icons/arrow_down.svg | 3 + assets/icons/arrow_left.svg | 4 +- assets/icons/arrow_right.svg | 4 +- assets/icons/arrow_up.svg | 3 + assets/icons/command.svg | 3 + assets/icons/control.svg | 3 + assets/icons/option.svg | 3 + assets/icons/return.svg | 3 + assets/icons/shift.svg | 3 + crates/theme2/src/default_colors.rs | 24 +++---- crates/theme2/src/one_themes.rs | 4 +- crates/ui2/src/components/icon.rs | 18 ++++- crates/ui2/src/components/keybinding.rs | 90 +++++++++++++++++++------ 13 files changed, 126 insertions(+), 39 deletions(-) create mode 100644 assets/icons/arrow_down.svg create mode 100644 assets/icons/arrow_up.svg create mode 100644 assets/icons/command.svg create mode 100644 assets/icons/control.svg create mode 100644 assets/icons/option.svg create mode 100644 assets/icons/return.svg create mode 100644 assets/icons/shift.svg diff --git a/assets/icons/arrow_down.svg b/assets/icons/arrow_down.svg new file mode 100644 index 0000000000..7d78497e6d --- /dev/null +++ b/assets/icons/arrow_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/arrow_left.svg b/assets/icons/arrow_left.svg index 186c9c7457..57ee750490 100644 --- a/assets/icons/arrow_left.svg +++ b/assets/icons/arrow_left.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/icons/arrow_right.svg b/assets/icons/arrow_right.svg index 7bae7f4801..7a5b1174eb 100644 --- a/assets/icons/arrow_right.svg +++ b/assets/icons/arrow_right.svg @@ -1,3 +1,3 @@ - - + + diff --git a/assets/icons/arrow_up.svg b/assets/icons/arrow_up.svg new file mode 100644 index 0000000000..81dfee8042 --- /dev/null +++ b/assets/icons/arrow_up.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/command.svg b/assets/icons/command.svg new file mode 100644 index 0000000000..d38389aea4 --- /dev/null +++ b/assets/icons/command.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/control.svg b/assets/icons/control.svg new file mode 100644 index 0000000000..94189dc07d --- /dev/null +++ b/assets/icons/control.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/option.svg b/assets/icons/option.svg new file mode 100644 index 0000000000..9d54a6f34b --- /dev/null +++ b/assets/icons/option.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/return.svg b/assets/icons/return.svg new file mode 100644 index 0000000000..683519c306 --- /dev/null +++ b/assets/icons/return.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/shift.svg b/assets/icons/shift.svg new file mode 100644 index 0000000000..0232114777 --- /dev/null +++ b/assets/icons/shift.svg @@ -0,0 +1,3 @@ + + + diff --git a/crates/theme2/src/default_colors.rs b/crates/theme2/src/default_colors.rs index 91efecbfb3..4a47bc0536 100644 --- a/crates/theme2/src/default_colors.rs +++ b/crates/theme2/src/default_colors.rs @@ -23,15 +23,15 @@ impl ThemeColors { surface_background: neutral().light().step_2(), background: neutral().light().step_1(), element_background: neutral().light().step_3(), - element_hover: neutral().light().step_4(), - element_active: neutral().light().step_5(), - element_selected: neutral().light().step_5(), + element_hover: neutral().light_alpha().step_4(), + element_active: neutral().light_alpha().step_5(), + element_selected: neutral().light_alpha().step_5(), element_disabled: neutral().light_alpha().step_3(), drop_target_background: blue().light_alpha().step_2(), ghost_element_background: system.transparent, - ghost_element_hover: neutral().light().step_4(), - ghost_element_active: neutral().light().step_5(), - ghost_element_selected: neutral().light().step_5(), + ghost_element_hover: neutral().light_alpha().step_4(), + ghost_element_active: neutral().light_alpha().step_5(), + ghost_element_selected: neutral().light_alpha().step_5(), ghost_element_disabled: neutral().light_alpha().step_3(), text: yellow().light().step_9(), text_muted: neutral().light().step_11(), @@ -95,15 +95,15 @@ impl ThemeColors { surface_background: neutral().dark().step_2(), background: neutral().dark().step_1(), element_background: neutral().dark().step_3(), - element_hover: neutral().dark().step_4(), - element_active: neutral().dark().step_5(), - element_selected: neutral().dark().step_5(), + element_hover: neutral().dark_alpha().step_4(), + element_active: neutral().dark_alpha().step_5(), + element_selected: neutral().dark_alpha().step_5(), element_disabled: neutral().dark_alpha().step_3(), drop_target_background: blue().dark_alpha().step_2(), ghost_element_background: system.transparent, - ghost_element_hover: neutral().dark().step_4(), - ghost_element_active: neutral().dark().step_5(), - ghost_element_selected: neutral().dark().step_5(), + ghost_element_hover: neutral().dark_alpha().step_4(), + ghost_element_active: neutral().dark_alpha().step_5(), + ghost_element_selected: neutral().dark_alpha().step_5(), ghost_element_disabled: neutral().dark_alpha().step_3(), text: neutral().dark().step_12(), text_muted: neutral().dark().step_11(), diff --git a/crates/theme2/src/one_themes.rs b/crates/theme2/src/one_themes.rs index 733cd6c40b..533323ce51 100644 --- a/crates/theme2/src/one_themes.rs +++ b/crates/theme2/src/one_themes.rs @@ -20,7 +20,7 @@ pub fn one_family() -> ThemeFamily { pub(crate) fn one_dark() -> Theme { let bg = hsla(215. / 360., 12. / 100., 15. / 100., 1.); let editor = hsla(220. / 360., 12. / 100., 18. / 100., 1.); - let elevated_surface = hsla(220. / 360., 12. / 100., 18. / 100., 1.); + let elevated_surface = hsla(225. / 360., 12. / 100., 17. / 100., 1.); let blue = hsla(207.8 / 360., 81. / 100., 66. / 100., 1.0); let gray = hsla(218.8 / 360., 10. / 100., 40. / 100., 1.0); @@ -48,7 +48,7 @@ pub(crate) fn one_dark() -> Theme { elevated_surface_background: elevated_surface, surface_background: bg, background: bg, - element_background: elevated_surface, + element_background: hsla(223.0 / 360., 13. / 100., 21. / 100., 1.0), element_hover: hsla(225.0 / 360., 11.8 / 100., 26.7 / 100., 1.0), element_active: hsla(220.0 / 360., 11.8 / 100., 20.0 / 100., 1.0), element_selected: hsla(224.0 / 360., 11.3 / 100., 26.1 / 100., 1.0), diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index 38b4777925..48f60413c5 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -14,6 +14,8 @@ pub enum IconSize { pub enum Icon { Ai, ArrowLeft, + ArrowUp, + ArrowDown, ArrowRight, ArrowUpRight, AtSign, @@ -66,6 +68,11 @@ pub enum Icon { SplitMessage, Terminal, XCircle, + Command, + Control, + Shift, + Option, + Return, } impl Icon { @@ -74,6 +81,8 @@ impl Icon { Icon::Ai => "icons/ai.svg", Icon::ArrowLeft => "icons/arrow_left.svg", Icon::ArrowRight => "icons/arrow_right.svg", + Icon::ArrowUp => "icons/arrow_up.svg", + Icon::ArrowDown => "icons/arrow_down.svg", Icon::ArrowUpRight => "icons/arrow_up_right.svg", Icon::AtSign => "icons/at-sign.svg", Icon::AudioOff => "icons/speaker-off.svg", @@ -125,6 +134,11 @@ impl Icon { Icon::SplitMessage => "icons/split_message.svg", Icon::Terminal => "icons/terminal.svg", Icon::XCircle => "icons/error.svg", + Icon::Command => "icons/command.svg", + Icon::Control => "icons/control.svg", + Icon::Shift => "icons/shift.svg", + Icon::Option => "icons/option.svg", + Icon::Return => "icons/return.svg", } } } @@ -165,8 +179,8 @@ impl IconElement { fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { let svg_size = match self.size { - IconSize::Small => rems(0.75), - IconSize::Medium => rems(0.9375), + IconSize::Small => rems(14. / 16.), + IconSize::Medium => rems(16. / 16.), }; svg() diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 69396274fa..c0690ce1c7 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -1,7 +1,7 @@ -use gpui::{actions, Action}; +use gpui::{actions, relative, rems, Action, Styled}; use strum::EnumIter; -use crate::prelude::*; +use crate::{h_stack, prelude::*, Icon, IconElement, IconSize}; #[derive(Component, Clone)] pub struct KeyBinding { @@ -24,20 +24,46 @@ impl KeyBinding { Self { key_binding } } + fn icon_for_key(key: &str) -> Option { + match key { + "left" => Some(Icon::ArrowLeft), + "right" => Some(Icon::ArrowRight), + "up" => Some(Icon::ArrowUp), + "down" => Some(Icon::ArrowDown), + _ => None, + } + } + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { - div() - .flex() - .gap_2() + h_stack() + .flex_none() + .gap_1() .children(self.key_binding.keystrokes().iter().map(|keystroke| { - div() - .flex() - .gap_1() + let key_icon = Self::icon_for_key(&keystroke.key); + + h_stack() + .flex_none() + .gap_0p5() + .bg(cx.theme().colors().element_background) + .p_0p5() + .rounded_sm() .when(keystroke.modifiers.function, |el| el.child(Key::new("fn"))) - .when(keystroke.modifiers.control, |el| el.child(Key::new("^"))) - .when(keystroke.modifiers.alt, |el| el.child(Key::new("⌥"))) - .when(keystroke.modifiers.command, |el| el.child(Key::new("⌘"))) - .when(keystroke.modifiers.shift, |el| el.child(Key::new("⇧"))) - .child(Key::new(keystroke.key.clone())) + .when(keystroke.modifiers.control, |el| { + el.child(KeyIcon::new(Icon::Control)) + }) + .when(keystroke.modifiers.alt, |el| { + el.child(KeyIcon::new(Icon::Option)) + }) + .when(keystroke.modifiers.command, |el| { + el.child(KeyIcon::new(Icon::Command)) + }) + .when(keystroke.modifiers.shift, |el| { + el.child(KeyIcon::new(Icon::Shift)) + }) + .when_some(key_icon, |el, icon| el.child(KeyIcon::new(icon))) + .when(key_icon.is_none(), |el| { + el.child(Key::new(keystroke.key.to_uppercase().clone())) + }) })) } } @@ -53,25 +79,51 @@ impl Key { } fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + let single_char = self.key.len() == 1; + div() - .px_2() + // .px_0p5() .py_0() - .rounded_md() - .text_ui_sm() + .when(single_char, |el| { + el.w(rems(14. / 16.)).flex().flex_none().justify_center() + }) + .when(!single_char, |el| el.px_0p5()) + .h(rems(14. / 16.)) + // .rounded_md() + .text_ui() + .line_height(relative(1.)) .text_color(cx.theme().colors().text) - .bg(cx.theme().colors().element_background) + // .bg(cx.theme().colors().element_background) .child(self.key.clone()) } } +#[derive(Component)] +pub struct KeyIcon { + icon: Icon, +} + +impl KeyIcon { + pub fn new(icon: Icon) -> Self { + Self { icon } + } + + fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + div() + .w(rems(14. / 16.)) + // .bg(cx.theme().colors().element_background) + .child(IconElement::new(self.icon).size(IconSize::Small)) + } +} + // NOTE: The order the modifier keys appear in this enum impacts the order in // which they are rendered in the UI. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)] pub enum ModifierKey { Control, - Alt, - Command, + Alt, // Option Shift, + Command, } actions!(NoAction); From a9cb6589dd2a7764db3648e5897fb77cf1c684a5 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 28 Nov 2023 14:40:26 -0500 Subject: [PATCH 2/6] Update keybinding.rs --- crates/ui2/src/components/keybinding.rs | 90 ++++++++++++++++++++----- 1 file changed, 74 insertions(+), 16 deletions(-) diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 1da0425ad3..15e365e526 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -1,5 +1,5 @@ -use crate::prelude::*; -use gpui::{Action, Div, IntoElement}; +use crate::{h_stack, prelude::*, Icon, IconElement, IconSize}; +use gpui::{relative, rems, Action, Div, IntoElement, Keystroke}; #[derive(IntoElement, Clone)] pub struct KeyBinding { @@ -14,19 +14,35 @@ impl RenderOnce for KeyBinding { type Rendered = Div; fn render(self, cx: &mut WindowContext) -> Self::Rendered { - div() - .flex() + h_stack() + .flex_none() .gap_2() .children(self.key_binding.keystrokes().iter().map(|keystroke| { - div() - .flex() - .gap_1() + let key_icon = Self::icon_for_key(&keystroke); + + h_stack() + .flex_none() + .gap_0p5() + .bg(cx.theme().colors().element_background) + .p_0p5() + .rounded_sm() .when(keystroke.modifiers.function, |el| el.child(Key::new("fn"))) - .when(keystroke.modifiers.control, |el| el.child(Key::new("^"))) - .when(keystroke.modifiers.alt, |el| el.child(Key::new("⌥"))) - .when(keystroke.modifiers.command, |el| el.child(Key::new("⌘"))) - .when(keystroke.modifiers.shift, |el| el.child(Key::new("⇧"))) - .child(Key::new(keystroke.key.clone())) + .when(keystroke.modifiers.control, |el| { + el.child(KeyIcon::new(Icon::Control)) + }) + .when(keystroke.modifiers.alt, |el| { + el.child(KeyIcon::new(Icon::Option)) + }) + .when(keystroke.modifiers.command, |el| { + el.child(KeyIcon::new(Icon::Command)) + }) + .when(keystroke.modifiers.shift, |el| { + el.child(KeyIcon::new(Icon::Shift)) + }) + // .when_some(key_icon, |el, icon| el.child(KeyIcon::new(icon))) + .when(key_icon.is_none(), |el| { + el.child(Key::new(keystroke.key.to_uppercase().clone())) + }) })) } } @@ -39,6 +55,22 @@ impl KeyBinding { Some(Self::new(key_binding)) } + fn icon_for_key(keystroke: &Keystroke) -> Option { + let mut icon: Option = None; + + if keystroke.key == "left".to_string() { + icon = Some(Icon::ArrowLeft); + } else if keystroke.key == "right".to_string() { + icon = Some(Icon::ArrowRight); + } else if keystroke.key == "up".to_string() { + icon = Some(Icon::ArrowUp); + } else if keystroke.key == "down".to_string() { + icon = Some(Icon::ArrowDown); + } + + icon + } + pub fn new(key_binding: gpui::KeyBinding) -> Self { Self { key_binding } } @@ -53,13 +85,18 @@ impl RenderOnce for Key { type Rendered = Div; fn render(self, cx: &mut WindowContext) -> Self::Rendered { + let single_char = self.key.len() == 1; + div() - .px_2() .py_0() - .rounded_md() - .text_ui_sm() + .when(single_char, |el| { + el.w(rems(14. / 16.)).flex().flex_none().justify_center() + }) + .when(!single_char, |el| el.px_0p5()) + .h(rems(14. / 16.)) + .text_ui() + .line_height(relative(1.)) .text_color(cx.theme().colors().text) - .bg(cx.theme().colors().element_background) .child(self.key.clone()) } } @@ -69,3 +106,24 @@ impl Key { Self { key: key.into() } } } + +#[derive(IntoElement)] +pub struct KeyIcon { + icon: Icon, +} + +impl RenderOnce for KeyIcon { + type Rendered = Div; + + fn render(self, cx: &mut WindowContext) -> Self::Rendered { + div() + .w(rems(14. / 16.)) + .child(IconElement::new(self.icon).size(IconSize::Small)) + } +} + +impl KeyIcon { + pub fn new(icon: Icon) -> Self { + Self { icon } + } +} From 40bbbd3226fd66ed9b98453537034031081ecb17 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 28 Nov 2023 15:06:37 -0500 Subject: [PATCH 3/6] Update command_palette.rs --- .../command_palette2/src/command_palette.rs | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 5f3fb4a985..ec77d93561 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -1,7 +1,7 @@ use collections::{CommandPaletteFilter, HashMap}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, + actions, rems, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView, }; use picker::{Picker, PickerDelegate}; @@ -79,7 +79,10 @@ impl Render for CommandPalette { type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - v_stack().w_96().child(self.picker.clone()) + v_stack() + .min_w_96() + .max_w(rems(36.)) + .child(self.picker.clone()) } } @@ -301,15 +304,19 @@ impl PickerDelegate for CommandPaletteDelegate { }; Some( - ListItem::new(ix).selected(selected).child( - h_stack() - .justify_between() - .child(HighlightedLabel::new( - command.name.clone(), - r#match.positions.clone(), - )) - .children(KeyBinding::for_action(&*command.action, cx)), - ), + ListItem::new(ix) + .variant(ui::ListItemVariant::Inset) + .selected(selected) + .child( + h_stack() + .w_full() + .justify_between() + .child(HighlightedLabel::new( + command.name.clone(), + r#match.positions.clone(), + )) + .children(KeyBinding::for_action(&*command.action, cx)), + ), ) } } From 21755c7d209a92e249555200300efa5cce0cb355 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 28 Nov 2023 15:12:40 -0500 Subject: [PATCH 4/6] Update keybinding.rs --- crates/ui2/src/components/keybinding.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index d11be1f4fc..15e365e526 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -13,7 +13,7 @@ pub struct KeyBinding { impl RenderOnce for KeyBinding { type Rendered = Div; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Rendered { h_stack() .flex_none() .gap_2() From 525fe70de6b62e6dcd11f06300c1dfe37623ff3c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 28 Nov 2023 15:15:49 -0500 Subject: [PATCH 5/6] Fix missing arrows --- crates/command_palette2/src/command_palette.rs | 5 +---- crates/ui2/src/components/keybinding.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 048749a02d..6a11f3f7ea 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -79,10 +79,7 @@ impl Render for CommandPalette { type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - v_stack() - .min_w_96() - .max_w(rems(36.)) - .child(self.picker.clone()) + v_stack().min_w_96().child(self.picker.clone()) } } diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 15e365e526..4bf98a9466 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -39,7 +39,7 @@ impl RenderOnce for KeyBinding { .when(keystroke.modifiers.shift, |el| { el.child(KeyIcon::new(Icon::Shift)) }) - // .when_some(key_icon, |el, icon| el.child(KeyIcon::new(icon))) + .when_some(key_icon, |el, icon| el.child(KeyIcon::new(icon))) .when(key_icon.is_none(), |el| { el.child(Key::new(keystroke.key.to_uppercase().clone())) }) From b24a3b8fcb5093978fb339d70c50a64a62b3bca2 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 28 Nov 2023 15:17:09 -0500 Subject: [PATCH 6/6] Unused imports --- crates/command_palette2/src/command_palette.rs | 2 +- crates/ui2/src/components/keybinding.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 6a11f3f7ea..076a2625a1 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -1,7 +1,7 @@ use collections::{CommandPaletteFilter, HashMap}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, rems, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, + actions, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView, }; use picker::{Picker, PickerDelegate}; diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 4bf98a9466..993e2f323e 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -115,7 +115,7 @@ pub struct KeyIcon { impl RenderOnce for KeyIcon { type Rendered = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { div() .w(rems(14. / 16.)) .child(IconElement::new(self.icon).size(IconSize::Small))