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