1use gpui::{Div, SharedString, Svg, div, prelude::*, px};
7use theme::{TextStyle, Theme, ThemeExt, Typeset, ink};
8
9pub trait Content: ThemeExt {
10 fn badge(&self, label: impl Into<SharedString>) -> Div {
12 let theme = self.theme();
13 div()
14 .flex_none()
15 .px(px(8.0))
16 .py(px(2.0))
17 .rounded_full()
18 .border_1()
19 .border_color(theme.border)
20 .text_style(TextStyle::Caption)
21 .text_color(theme.text_muted)
22 .child(label.into())
23 }
24
25 fn badge_active(&self, label: impl Into<SharedString>) -> Div {
28 let theme = self.theme();
29 let emerald = theme.success;
30 let emerald_text = theme.success_muted; div()
32 .flex_none()
33 .px(px(8.0))
34 .py(px(2.0))
35 .rounded_full()
36 .bg(emerald.opacity(0.12))
37 .text_style(TextStyle::Caption)
38 .text_color(emerald_text.opacity(0.9))
39 .child(label.into())
40 }
41
42 fn avatar(&self, initials: impl Into<SharedString>) -> Div {
45 let theme = self.theme();
46 div()
47 .flex_none()
48 .size(px(28.0))
49 .rounded_full()
50 .bg(ink(0.12))
51 .flex()
52 .items_center()
53 .justify_center()
54 .text_style(TextStyle::Subheadline)
55 .font_weight(gpui::FontWeight::MEDIUM)
56 .text_color(theme.text_muted)
57 .child(initials.into())
58 }
59
60 fn tag(&self, label: impl Into<SharedString>) -> Div {
63 let theme = self.theme();
64 div()
65 .self_start()
66 .flex()
67 .flex_row()
68 .items_center()
69 .gap(px(5.0))
70 .pl(px(8.0))
71 .pr(px(5.0))
72 .py(px(3.0))
73 .rounded(px(Theme::control_radius()))
74 .bg(ink(0.07))
75 .border_1()
76 .border_color(theme.border)
77 .text_style(TextStyle::Callout)
78 .text_color(theme.text)
79 .child(label.into())
80 .child(
81 crate::icons::icon(crate::icons::glyph::X)
82 .size(px(10.0))
83 .text_color(theme.text_faint),
84 )
85 }
86
87 fn breadcrumb(&self) -> Div {
90 div()
91 .self_start()
92 .flex()
93 .flex_row()
94 .items_center()
95 .gap(px(4.0))
96 .min_w_0()
97 }
98
99 fn breadcrumb_item(&self, label: impl Into<SharedString>, current: bool) -> Div {
101 let theme = self.theme();
102 let mut crumb = div()
103 .min_w_0()
104 .truncate()
105 .text_style(TextStyle::Callout)
106 .child(label.into());
107 crumb = if current {
108 crumb.text_color(theme.text)
109 } else {
110 crumb.text_color(theme.text_muted).cursor_pointer()
111 };
112 crumb
113 }
114
115 fn breadcrumb_separator(&self) -> Svg {
117 let theme = self.theme();
118 crate::icons::icon(crate::icons::glyph::ChevronRight)
119 .size(px(12.0))
120 .text_color(theme.text_faint)
121 }
122
123 fn empty_state(
125 &self,
126 icon_path: &'static [u8],
127 title: impl Into<SharedString>,
128 hint: impl Into<SharedString>,
129 ) -> Div {
130 let theme = self.theme();
131 div()
132 .w_full()
133 .flex()
134 .flex_col()
135 .items_center()
136 .justify_center()
137 .gap(px(6.0))
138 .py(px(40.0))
139 .child(
140 crate::icons::icon(icon_path)
141 .size(px(24.0))
142 .text_color(theme.text_faint),
143 )
144 .child(
145 div()
146 .text_style(TextStyle::Headline)
147 .text_color(theme.text)
148 .child(title.into()),
149 )
150 .child(
151 div()
152 .text_style(TextStyle::Callout)
153 .text_color(theme.text_muted)
154 .child(hint.into()),
155 )
156 }
157}
158
159impl Content for Theme {}