icon.rs

  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    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    Plus,
 97    Public,
 98    Quote,
 99    Replace,
100    ReplaceAll,
101    ReplaceNext,
102    Return,
103    Screen,
104    SelectAll,
105    Shift,
106    Snip,
107    Space,
108    Split,
109    Tab,
110    Terminal,
111    Update,
112    WholeWord,
113    XCircle,
114    ZedXCopilot,
115}
116
117impl IconName {
118    pub fn path(self) -> &'static str {
119        match self {
120            IconName::Ai => "icons/ai.svg",
121            IconName::ArrowDown => "icons/arrow_down.svg",
122            IconName::ArrowLeft => "icons/arrow_left.svg",
123            IconName::ArrowRight => "icons/arrow_right.svg",
124            IconName::ArrowUp => "icons/arrow_up.svg",
125            IconName::ArrowUpRight => "icons/arrow_up_right.svg",
126            IconName::ArrowCircle => "icons/arrow_circle.svg",
127            IconName::AtSign => "icons/at_sign.svg",
128            IconName::AudioOff => "icons/speaker_off.svg",
129            IconName::AudioOn => "icons/speaker_loud.svg",
130            IconName::Backspace => "icons/backspace.svg",
131            IconName::Bell => "icons/bell.svg",
132            IconName::BellOff => "icons/bell_off.svg",
133            IconName::BellRing => "icons/bell_ring.svg",
134            IconName::BellDot => "icons/bell_dot.svg",
135            IconName::Bolt => "icons/bolt.svg",
136            IconName::CaseSensitive => "icons/case_insensitive.svg",
137            IconName::Check => "icons/check.svg",
138            IconName::ChevronDown => "icons/chevron_down.svg",
139            IconName::ChevronLeft => "icons/chevron_left.svg",
140            IconName::ChevronRight => "icons/chevron_right.svg",
141            IconName::ChevronUp => "icons/chevron_up.svg",
142            IconName::Close => "icons/x.svg",
143            IconName::Collab => "icons/user_group_16.svg",
144            IconName::Command => "icons/command.svg",
145            IconName::Control => "icons/control.svg",
146            IconName::Copilot => "icons/copilot.svg",
147            IconName::CopilotDisabled => "icons/copilot_disabled.svg",
148            IconName::CopilotError => "icons/copilot_error.svg",
149            IconName::CopilotInit => "icons/copilot_init.svg",
150            IconName::Copy => "icons/copy.svg",
151            IconName::Dash => "icons/dash.svg",
152            IconName::Delete => "icons/delete.svg",
153            IconName::Disconnected => "icons/disconnected.svg",
154            IconName::Ellipsis => "icons/ellipsis.svg",
155            IconName::Envelope => "icons/feedback.svg",
156            IconName::Escape => "icons/escape.svg",
157            IconName::ExclamationTriangle => "icons/warning.svg",
158            IconName::Exit => "icons/exit.svg",
159            IconName::ExternalLink => "icons/external_link.svg",
160            IconName::File => "icons/file.svg",
161            IconName::FileDoc => "icons/file_icons/book.svg",
162            IconName::FileGeneric => "icons/file_icons/file.svg",
163            IconName::FileGit => "icons/file_icons/git.svg",
164            IconName::FileLock => "icons/file_icons/lock.svg",
165            IconName::FileRust => "icons/file_icons/rust.svg",
166            IconName::FileToml => "icons/file_icons/toml.svg",
167            IconName::FileTree => "icons/project.svg",
168            IconName::Filter => "icons/filter.svg",
169            IconName::Folder => "icons/file_icons/folder.svg",
170            IconName::FolderOpen => "icons/file_icons/folder_open.svg",
171            IconName::FolderX => "icons/stop_sharing.svg",
172            IconName::Github => "icons/github.svg",
173            IconName::Hash => "icons/hash.svg",
174            IconName::InlayHint => "icons/inlay_hint.svg",
175            IconName::Link => "icons/link.svg",
176            IconName::MagicWand => "icons/magic_wand.svg",
177            IconName::MagnifyingGlass => "icons/magnifying_glass.svg",
178            IconName::MailOpen => "icons/mail_open.svg",
179            IconName::Maximize => "icons/maximize.svg",
180            IconName::Menu => "icons/menu.svg",
181            IconName::MessageBubbles => "icons/conversations.svg",
182            IconName::Mic => "icons/mic.svg",
183            IconName::MicMute => "icons/mic_mute.svg",
184            IconName::Minimize => "icons/minimize.svg",
185            IconName::Option => "icons/option.svg",
186            IconName::PageDown => "icons/page_down.svg",
187            IconName::PageUp => "icons/page_up.svg",
188            IconName::Plus => "icons/plus.svg",
189            IconName::Public => "icons/public.svg",
190            IconName::Quote => "icons/quote.svg",
191            IconName::Replace => "icons/replace.svg",
192            IconName::ReplaceAll => "icons/replace_all.svg",
193            IconName::ReplaceNext => "icons/replace_next.svg",
194            IconName::Return => "icons/return.svg",
195            IconName::Screen => "icons/desktop.svg",
196            IconName::SelectAll => "icons/select_all.svg",
197            IconName::Shift => "icons/shift.svg",
198            IconName::Snip => "icons/snip.svg",
199            IconName::Space => "icons/space.svg",
200            IconName::Split => "icons/split.svg",
201            IconName::Tab => "icons/tab.svg",
202            IconName::Terminal => "icons/terminal.svg",
203            IconName::Update => "icons/update.svg",
204            IconName::WholeWord => "icons/word_search.svg",
205            IconName::XCircle => "icons/error.svg",
206            IconName::ZedXCopilot => "icons/zed_x_copilot.svg",
207        }
208    }
209}
210
211#[derive(IntoElement)]
212pub struct Icon {
213    path: SharedString,
214    color: Color,
215    size: IconSize,
216}
217
218impl Icon {
219    pub fn new(icon: IconName) -> Self {
220        Self {
221            path: icon.path().into(),
222            color: Color::default(),
223            size: IconSize::default(),
224        }
225    }
226
227    pub fn from_path(path: impl Into<SharedString>) -> Self {
228        Self {
229            path: path.into(),
230            color: Color::default(),
231            size: IconSize::default(),
232        }
233    }
234
235    pub fn color(mut self, color: Color) -> Self {
236        self.color = color;
237        self
238    }
239
240    pub fn size(mut self, size: IconSize) -> Self {
241        self.size = size;
242        self
243    }
244}
245
246impl RenderOnce for Icon {
247    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
248        svg()
249            .size(self.size.rems())
250            .flex_none()
251            .path(self.path)
252            .text_color(self.color.color(cx))
253    }
254}