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