herogpui_components/
kbd.rs1use gpui::{px, AnyElement, App, IntoElement, ParentElement, Pixels, RenderOnce, Styled, Window};
4use herogpui_theme::ActiveTheme;
5
6#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
8pub enum KbdVariant {
9 #[default]
11 Default,
12 Light,
14}
15
16impl KbdVariant {
17 pub const ALL: [KbdVariant; 2] = [KbdVariant::Default, KbdVariant::Light];
19
20 pub fn label(self) -> &'static str {
22 match self {
23 KbdVariant::Default => "Default",
24 KbdVariant::Light => "Light",
25 }
26 }
27}
28
29#[must_use = "a component does nothing until it is rendered: add it as a child or return it from `render`"]
31#[derive(IntoElement)]
32pub struct Kbd {
33 variant: KbdVariant,
34 children: Vec<AnyElement>,
35 radius: Option<Pixels>,
37 sx: Option<Box<gpui::StyleRefinement>>,
39}
40
41impl Kbd {
42 pub fn new() -> Self {
44 Self {
45 variant: KbdVariant::Default,
46 children: Vec::new(),
47 radius: None,
48 sx: None,
49 }
50 }
51
52 pub fn variant(mut self, v: KbdVariant) -> Self {
54 self.variant = v;
55 self
56 }
57
58 pub fn radius(mut self, radius: impl Into<Pixels>) -> Self {
62 self.radius = Some(radius.into());
63 self
64 }
65
66 pub fn sx(mut self, style: impl FnOnce(gpui::Div) -> gpui::Div) -> Self {
71 crate::util::refine_sx(&mut self.sx, style);
72 self
73 }
74}
75
76impl Default for Kbd {
77 fn default() -> Self {
78 Self::new()
79 }
80}
81
82impl ParentElement for Kbd {
83 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
84 self.children.extend(elements);
85 }
86}
87
88impl RenderOnce for Kbd {
89 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
90 let colors = cx.colors();
91
92 let (h, text) = (px(24.), px(14.));
93
94 let mut el = gpui::div()
95 .flex()
96 .items_center()
97 .justify_center()
98 .text_center()
99 .gap(px(2.))
100 .px(px(8.))
101 .h(h)
102 .rounded(self.radius.unwrap_or_else(|| crate::util::key_radius(cx)))
103 .text_size(text)
106 .line_height(px(20.))
107 .font_weight(gpui::FontWeight::MEDIUM)
108 .whitespace_nowrap()
109 .text_color(colors.muted);
110
111 el = match self.variant {
112 KbdVariant::Default => el.bg(colors.default.color),
113 KbdVariant::Light => el.bg(gpui::transparent_black()),
114 };
115
116 el = el.children(self.children);
119 el = crate::util::apply_sx(el, &self.sx);
120 el
121 }
122}
123
124crate::util::impl_component_styled!(Kbd);