1use gpui::{rems, svg, IntoElement, Rems};
2use strum::EnumIter;
3
4use crate::prelude::*;
5
6#[derive(Default, PartialEq, Copy, Clone)]
7pub enum IconSize {
8 Indicator,
9 XSmall,
10 Small,
11 #[default]
12 Medium,
13}
14
15impl IconSize {
16 pub fn rems(self) -> Rems {
17 match self {
18 IconSize::Indicator => rems(10. / 16.),
19 IconSize::XSmall => rems(12. / 16.),
20 IconSize::Small => rems(14. / 16.),
21 IconSize::Medium => rems(16. / 16.),
22 }
23 }
24}
25
26#[derive(Debug, PartialEq, Copy, Clone, EnumIter)]
27pub enum IconName {
28 Ai,
29 ArrowDown,
30 ArrowLeft,
31 ArrowRight,
32 ArrowUp,
33 ArrowUpRight,
34 ArrowCircle,
35 AtSign,
36 AudioOff,
37 AudioOn,
38 Backspace,
39 Bell,
40 BellOff,
41 BellRing,
42 Bolt,
43 CaseSensitive,
44 Check,
45 ChevronDown,
46 ChevronLeft,
47 ChevronRight,
48 ChevronUp,
49 Close,
50 Collab,
51 Command,
52 Control,
53 Copilot,
54 CopilotDisabled,
55 CopilotError,
56 CopilotInit,
57 Copy,
58 Dash,
59 Delete,
60 Disconnected,
61 Ellipsis,
62 Envelope,
63 Escape,
64 ExclamationTriangle,
65 Exit,
66 ExternalLink,
67 File,
68 FileDoc,
69 FileGeneric,
70 FileGit,
71 FileLock,
72 FileRust,
73 FileToml,
74 FileTree,
75 Filter,
76 Folder,
77 FolderOpen,
78 FolderX,
79 Github,
80 Hash,
81 InlayHint,
82 Link,
83 MagicWand,
84 MagnifyingGlass,
85 MailOpen,
86 Maximize,
87 Menu,
88 MessageBubbles,
89 Mic,
90 MicMute,
91 Minimize,
92 Option,
93 PageDown,
94 PageUp,
95 Plus,
96 Public,
97 Quote,
98 Replace,
99 ReplaceAll,
100 ReplaceNext,
101 Return,
102 Screen,
103 SelectAll,
104 Shift,
105 Snip,
106 Space,
107 Split,
108 Tab,
109 Terminal,
110 Update,
111 WholeWord,
112 XCircle,
113 ZedXCopilot,
114}
115
116impl IconName {
117 pub fn path(self) -> &'static str {
118 match self {
119 IconName::Ai => "icons/ai.svg",
120 IconName::ArrowDown => "icons/arrow_down.svg",
121 IconName::ArrowLeft => "icons/arrow_left.svg",
122 IconName::ArrowRight => "icons/arrow_right.svg",
123 IconName::ArrowUp => "icons/arrow_up.svg",
124 IconName::ArrowUpRight => "icons/arrow_up_right.svg",
125 IconName::ArrowCircle => "icons/arrow_circle.svg",
126 IconName::AtSign => "icons/at_sign.svg",
127 IconName::AudioOff => "icons/speaker_off.svg",
128 IconName::AudioOn => "icons/speaker_loud.svg",
129 IconName::Backspace => "icons/backspace.svg",
130 IconName::Bell => "icons/bell.svg",
131 IconName::BellOff => "icons/bell_off.svg",
132 IconName::BellRing => "icons/bell_ring.svg",
133 IconName::Bolt => "icons/bolt.svg",
134 IconName::CaseSensitive => "icons/case_insensitive.svg",
135 IconName::Check => "icons/check.svg",
136 IconName::ChevronDown => "icons/chevron_down.svg",
137 IconName::ChevronLeft => "icons/chevron_left.svg",
138 IconName::ChevronRight => "icons/chevron_right.svg",
139 IconName::ChevronUp => "icons/chevron_up.svg",
140 IconName::Close => "icons/x.svg",
141 IconName::Collab => "icons/user_group_16.svg",
142 IconName::Command => "icons/command.svg",
143 IconName::Control => "icons/control.svg",
144 IconName::Copilot => "icons/copilot.svg",
145 IconName::CopilotDisabled => "icons/copilot_disabled.svg",
146 IconName::CopilotError => "icons/copilot_error.svg",
147 IconName::CopilotInit => "icons/copilot_init.svg",
148 IconName::Copy => "icons/copy.svg",
149 IconName::Dash => "icons/dash.svg",
150 IconName::Delete => "icons/delete.svg",
151 IconName::Disconnected => "icons/disconnected.svg",
152 IconName::Ellipsis => "icons/ellipsis.svg",
153 IconName::Envelope => "icons/feedback.svg",
154 IconName::Escape => "icons/escape.svg",
155 IconName::ExclamationTriangle => "icons/warning.svg",
156 IconName::Exit => "icons/exit.svg",
157 IconName::ExternalLink => "icons/external_link.svg",
158 IconName::File => "icons/file.svg",
159 IconName::FileDoc => "icons/file_icons/book.svg",
160 IconName::FileGeneric => "icons/file_icons/file.svg",
161 IconName::FileGit => "icons/file_icons/git.svg",
162 IconName::FileLock => "icons/file_icons/lock.svg",
163 IconName::FileRust => "icons/file_icons/rust.svg",
164 IconName::FileToml => "icons/file_icons/toml.svg",
165 IconName::FileTree => "icons/project.svg",
166 IconName::Filter => "icons/filter.svg",
167 IconName::Folder => "icons/file_icons/folder.svg",
168 IconName::FolderOpen => "icons/file_icons/folder_open.svg",
169 IconName::FolderX => "icons/stop_sharing.svg",
170 IconName::Github => "icons/github.svg",
171 IconName::Hash => "icons/hash.svg",
172 IconName::InlayHint => "icons/inlay_hint.svg",
173 IconName::Link => "icons/link.svg",
174 IconName::MagicWand => "icons/magic_wand.svg",
175 IconName::MagnifyingGlass => "icons/magnifying_glass.svg",
176 IconName::MailOpen => "icons/mail_open.svg",
177 IconName::Maximize => "icons/maximize.svg",
178 IconName::Menu => "icons/menu.svg",
179 IconName::MessageBubbles => "icons/conversations.svg",
180 IconName::Mic => "icons/mic.svg",
181 IconName::MicMute => "icons/mic_mute.svg",
182 IconName::Minimize => "icons/minimize.svg",
183 IconName::Option => "icons/option.svg",
184 IconName::PageDown => "icons/page_down.svg",
185 IconName::PageUp => "icons/page_up.svg",
186 IconName::Plus => "icons/plus.svg",
187 IconName::Public => "icons/public.svg",
188 IconName::Quote => "icons/quote.svg",
189 IconName::Replace => "icons/replace.svg",
190 IconName::ReplaceAll => "icons/replace_all.svg",
191 IconName::ReplaceNext => "icons/replace_next.svg",
192 IconName::Return => "icons/return.svg",
193 IconName::Screen => "icons/desktop.svg",
194 IconName::SelectAll => "icons/select_all.svg",
195 IconName::Shift => "icons/shift.svg",
196 IconName::Snip => "icons/snip.svg",
197 IconName::Space => "icons/space.svg",
198 IconName::Split => "icons/split.svg",
199 IconName::Tab => "icons/tab.svg",
200 IconName::Terminal => "icons/terminal.svg",
201 IconName::Update => "icons/update.svg",
202 IconName::WholeWord => "icons/word_search.svg",
203 IconName::XCircle => "icons/error.svg",
204 IconName::ZedXCopilot => "icons/zed_x_copilot.svg",
205 }
206 }
207}
208
209#[derive(IntoElement)]
210pub struct Icon {
211 path: SharedString,
212 color: Color,
213 size: IconSize,
214}
215
216impl Icon {
217 pub fn new(icon: IconName) -> Self {
218 Self {
219 path: icon.path().into(),
220 color: Color::default(),
221 size: IconSize::default(),
222 }
223 }
224
225 pub fn from_path(path: impl Into<SharedString>) -> Self {
226 Self {
227 path: path.into(),
228 color: Color::default(),
229 size: IconSize::default(),
230 }
231 }
232
233 pub fn color(mut self, color: Color) -> Self {
234 self.color = color;
235 self
236 }
237
238 pub fn size(mut self, size: IconSize) -> Self {
239 self.size = size;
240 self
241 }
242}
243
244impl RenderOnce for Icon {
245 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
246 svg()
247 .size(self.size.rems())
248 .flex_none()
249 .path(self.path)
250 .text_color(self.color.color(cx))
251 }
252}