kb

Nate Butler created

Change summary

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                |  1 
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, 124 insertions(+), 39 deletions(-)

Detailed changes

assets/icons/arrow_down.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.00001 12L3.5 7.50001M8.00001 12L12.5 7.50001M8.00001 12L8.00001 3.00001" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

assets/icons/arrow_left.svg 🔗

@@ -1,3 +1,3 @@
-<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M3.125 6.99344L6.35938 3.63281M3.125 6.99344L6.35938 10.3672M3.125 6.99344H11" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.5 7.50001L8 3M3.5 7.50001L8 12M3.5 7.50001H12.5" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
 </svg>

assets/icons/arrow_right.svg 🔗

@@ -1,3 +1,3 @@
-<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M10.8906 7.00125L7.64062 3.64062M10.8906 7.00125L7.64062 10.375M10.8906 7.00125H3" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12.5 7.5L8 12M12.5 7.5L8 3M12.5 7.5L3.5 7.5" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
 </svg>

assets/icons/arrow_up.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7.99999 3.00001L12.5 7.50001M7.99999 3.00001L3.49999 7.50001M7.99999 3.00001L7.99999 12" stroke="black" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

assets/icons/command.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">

assets/icons/control.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3.5 6.12488L7.64656 1.97853C7.84183 1.78328 8.1584 1.78329 8.35366 1.97854L12.5 6.12488" stroke="black" stroke-width="1.25" stroke-linecap="round"/>
+</svg>

assets/icons/option.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5.35606 1.005H1.62545C1.28002 1.005 1 1.28502 1 1.63044C1 1.97587 1.28002 2.25589 1.62545 2.25589L5.35606 2.25589C5.62311 2.25589 5.8607 2.42545 5.94752 2.67799L9.75029 13.7387C10.0108 14.4963 10.7235 15.005 11.5247 15.005H14.3746C14.72 15.005 15 14.725 15 14.3796C15 14.0341 14.72 13.7541 14.3746 13.7541H11.5247C11.2576 13.7541 11.02 13.5845 10.9332 13.332L7.13046 2.27128C6.86998 1.51366 6.15721 1.005 5.35606 1.005ZM14.3745 1.005H9.75125C9.40582 1.005 9.1258 1.28502 9.1258 1.63044C9.1258 1.97587 9.40582 2.25589 9.75125 2.25589L14.3745 2.25589C14.72 2.25589 15 1.97587 15 1.63044C15 1.28502 14.72 1.005 14.3745 1.005Z" fill="black"/>
+</svg>

assets/icons/return.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8.375 1.63C8.375 1.28482 8.65482 1.005 9 1.005H12.375C13.8247 1.005 15 2.18025 15 3.63V7.625C15 9.07474 13.8247 10.25 12.375 10.25H3.13388L6.07194 13.1881C6.31602 13.4321 6.31602 13.8279 6.07194 14.0719C5.82786 14.316 5.43214 14.316 5.18806 14.0719L1.18306 10.0669C0.938981 9.82286 0.938981 9.42714 1.18306 9.18306L5.18306 5.18306C5.42714 4.93898 5.82286 4.93898 6.06694 5.18306C6.31102 5.42714 6.31102 5.82286 6.06694 6.06694L3.13388 9H12.375C13.1344 9 13.75 8.38439 13.75 7.625V3.63C13.75 2.87061 13.1344 2.255 12.375 2.255H9C8.65482 2.255 8.375 1.97518 8.375 1.63Z" fill="black"/>
+</svg>

assets/icons/shift.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.46475 7.99652L7.85304 2.15921C7.93223 2.07342 8.06777 2.07341 8.14696 2.15921L13.5352 7.99652C13.7126 8.18869 13.5763 8.5 13.3148 8.5H10.5V13.7C10.5 13.8657 10.3657 14 10.2 14H5.8C5.63431 14 5.5 13.8657 5.5 13.7V8.5H2.6852C2.42367 8.5 2.28737 8.18869 2.46475 7.99652Z" stroke="black" stroke-width="1.25"/>
+</svg>

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(),

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),

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<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
         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()

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<Icon> {
+        match key {
+            "left" => Some(Icon::ArrowLeft),
+            "right" => Some(Icon::ArrowRight),
+            "up" => Some(Icon::ArrowUp),
+            "down" => Some(Icon::ArrowDown),
+            _ => None,
+        }
+    }
+
     fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
-        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<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+        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<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+        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);