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    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}