Derive icon paths (#17816)

Nate Butler created

This PR improves adding and working with icons by using the new
`DerivePathStr` to derive icon paths.

This means paths no longer need to be manually specified, and the
`IconName` and file name will always be consistent between icons.

This PR does not do any work to standardize icons visually, remove
unused icons, or any other such cleanup.

Release Notes:

- N/A

Change summary

assets/icons/audio_off.svg                                |   1 
assets/icons/audio_on.svg                                 |   1 
assets/icons/case_sensitive.svg                           |   0 
assets/icons/close.svg                                    |   0 
assets/icons/cursor_i_beam.svg                            |   0 
assets/icons/cursor_text.svg                              |   0 
assets/icons/envelope.svg                                 |   0 
assets/icons/file_doc.svg                                 |   6 
assets/icons/file_generic.svg                             |   5 
assets/icons/file_git.svg                                 |   6 
assets/icons/file_lock.svg                                |   4 
assets/icons/file_rust.svg                                |   2 
assets/icons/file_toml.svg                                |   5 
assets/icons/file_tree.svg                                |   0 
assets/icons/folder.svg                                   |   3 
assets/icons/folder_open.svg                              |   4 
assets/icons/folder_x.svg                                 |   0 
assets/icons/message_bubbles.svg                          |   0 
assets/icons/screen.svg                                   |   0 
assets/icons/settings.svg                                 |   1 
assets/icons/settings_alt.svg                             |   0 
assets/icons/speaker_off.svg                              |   8 
assets/icons/user_group.svg                               |   0 
assets/icons/whole_word.svg                               |   0 
assets/icons/x_circle.svg                                 |   0 
crates/activity_indicator/src/activity_indicator.rs       |   6 
crates/assistant/src/assistant_panel.rs                   |   6 
crates/assistant/src/inline_assistant.rs                  |   2 
crates/assistant/src/slash_command/diagnostics_command.rs |   4 
crates/assistant/src/terminal_inline_assistant.rs         |   2 
crates/collab_ui/src/collab_panel.rs                      |   2 
crates/diagnostics/src/diagnostics.rs                     |   4 
crates/diagnostics/src/items.rs                           |   4 
crates/diagnostics/src/toolbar_controls.rs                |   2 
crates/quick_action_bar/src/quick_action_bar.rs           |   2 
crates/terminal_view/src/terminal_view.rs                 |   2 
crates/ui/src/components/icon.rs                          | 219 +-------
crates/ui/src/components/stories/list_header.rs           |   2 
crates/workspace/src/notifications.rs                     |  14 
39 files changed, 91 insertions(+), 226 deletions(-)

Detailed changes

assets/icons/audio_off.svg 🔗

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-volume-off"><path d="M16 9a5 5 0 0 1 .95 2.293"/><path d="M19.364 5.636a9 9 0 0 1 1.889 9.96"/><path d="m2 2 20 20"/><path d="m7 7-.587.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298V11"/><path d="M9.828 4.172A.686.686 0 0 1 11 4.657v.686"/></svg>

assets/icons/audio_on.svg 🔗

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-volume-2"><path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"/><path d="M16 9a5 5 0 0 1 0 6"/><path d="M19.364 18.364a9 9 0 0 0 0-12.728"/></svg>

assets/icons/file_doc.svg 🔗

@@ -0,0 +1,6 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M13 11V11.8374C13 11.9431 12.9665 12.046 12.9044 12.1315L12.1498 13.1691C12.0557 13.2985 11.9054 13.375 11.7454 13.375H4.25461C4.09464 13.375 3.94433 13.2985 3.85024 13.1691L3.09563 12.1315C3.03348 12.046 3 11.9431 3 11.8374V3" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M3 13V11L8 12H13V13H3Z" fill="black"/>
+<path d="M6.63246 3.04418C7.44914 3.31641 8 4.08069 8 4.94155V11.7306C8 12.0924 7.62757 12.3345 7.29693 12.1875L3.79693 10.632C3.61637 10.5518 3.5 10.3727 3.5 10.1751V2.69374C3.5 2.35246 3.83435 2.11148 4.15811 2.2194L6.63246 3.04418Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M9.5 3C8.67157 3 8 3.67157 8 4.5V13C8 12.1954 11.2366 12.0382 12.5017 12.0075C12.7778 12.0008 13 11.7761 13 11.5V3.5C13 3.22386 12.7761 3 12.5 3H9.5Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

assets/icons/file_generic.svg 🔗

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M3 5H11" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M3 8H13" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M3 11H9" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+</svg>

assets/icons/file_git.svg 🔗

@@ -0,0 +1,6 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5 13C6.10457 13 7 12.1046 7 11C7 9.89543 6.10457 9 5 9C3.89543 9 3 9.89543 3 11C3 12.1046 3.89543 13 5 13Z" stroke="black" stroke-width="1.5"/>
+<path d="M11 7C12.1046 7 13 6.10457 13 5C13 3.89543 12.1046 3 11 3C9.89543 3 9 3.89543 9 5C9 6.10457 9.89543 7 11 7Z" fill="black" stroke="black" stroke-width="1.5"/>
+<path d="M4.625 3.625V8.375" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M11 7C11 9.20914 9.20914 11 7 11" stroke="black" stroke-width="1.5"/>
+</svg>

assets/icons/file_lock.svg 🔗

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5 5C5 3.89543 5.89543 3 7 3H9C10.1046 3 11 3.89543 11 5V6H5V5Z" stroke="black" stroke-width="1.5"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M3.25 6.5C3.25 5.80964 3.80964 5.25 4.5 5.25H11.5C12.1904 5.25 12.75 5.80964 12.75 6.5V12.5C12.75 13.1904 12.1904 13.75 11.5 13.75H4.5C3.80964 13.75 3.25 13.1904 3.25 12.5V6.5ZM8.75 9.66146C8.90559 9.48517 9 9.25361 9 9C9 8.44772 8.55228 8 8 8C7.44772 8 7 8.44772 7 9C7 9.25361 7.09441 9.48517 7.25 9.66146V11C7.25 11.4142 7.58579 11.75 8 11.75C8.41421 11.75 8.75 11.4142 8.75 11V9.66146Z" fill="black"/>
+</svg>

assets/icons/file_rust.svg 🔗

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.27935 10.9821C5.32063 10.4038 4.9204 9.89049 4.35998 9.80276L3.60081 9.68387C3.37979 9.64945 3.20167 9.48001 3.15225 9.25614L3.01378 8.63511C2.96382 8.41235 3.05233 8.1807 3.23696 8.05125L3.8631 7.61242C4.33337 7.28297 4.47456 6.6369 4.18621 6.13364L3.79467 5.45092C3.68118 5.25261 3.69801 5.00374 3.83757 4.82321L4.22314 4.32436C4.3627 4.14438 4.59621 4.06994 4.81071 4.13772L5.57531 4.37769C6.11944 4.54879 6.70048 4.26159 6.90683 3.71886L7.1811 2.99782C7.26255 2.78395 7.46345 2.64285 7.68772 2.6423L8.31007 2.64063C8.53434 2.64007 8.73579 2.78006 8.81834 2.99337L9.09965 3.72275C9.30821 4.26214 9.88655 4.54712 10.429 4.37714L11.1632 4.14716C11.3772 4.07994 11.6096 4.15382 11.7492 4.3327L12.1374 4.83099" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>

assets/icons/file_toml.svg 🔗

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6 6H10" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M8 6V11" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+<path d="M5 3H3.5C3.22386 3 3 3.22386 3 3.5V12.5C3 12.7761 3.22386 13 3.5 13H5M11 3H12.5C12.7761 3 13 3.22386 13 3.5V12.5C13 12.7761 12.7761 13 12.5 13H11" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+</svg>

assets/icons/folder.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8.26046 3.97337C8.3527 4.17617 8.4795 4.47151 8.57375 4.69341C8.65258 4.87898 8.83437 4.99999 9.03599 4.99999H12.5C12.7761 4.99999 13 5.22385 13 5.49999V12.125C13 12.4011 12.7761 12.625 12.5 12.625H3.5C3.22386 12.625 3 12.4011 3 12.125V3.86932C3 3.59318 3.22386 3.36932 3.5 3.36932H7.34219C7.74141 3.36932 8.09483 3.60924 8.26046 3.97337Z" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
+</svg>

assets/icons/folder_open.svg 🔗

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.42782 7.2487C4.43495 6.97194 4.65009 6.75 4.91441 6.75H13.5293C13.7935 6.75 14.007 6.97194 13.9998 7.2487C13.9628 8.6885 13.7533 12.75 12.5721 12.75H3.375C4.55631 12.75 4.3907 8.6885 4.42782 7.2487Z" fill="black" stroke="black" stroke-width="1.5" stroke-linejoin="round"/>
+<path d="M5.19598 12.625H3.66515C3.42618 12.625 3.22289 12.4453 3.18626 12.2017L1.94333 3.93602C1.89776 3.63295 2.12496 3.35938 2.42223 3.35938H5.78585C6.11241 3.35938 6.41702 3.52903 6.59618 3.81071L6.94517 4.35938H9.92811C10.4007 4.35938 10.8044 4.71102 10.8836 5.1917L11.1251 6.65624" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

assets/icons/settings.svg 🔗

@@ -0,0 +1,4 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">

assets/icons/speaker_off.svg 🔗

@@ -1,8 +0,0 @@
-<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
-  <path
-    fill-rule="evenodd"
-    clip-rule="evenodd"
-    d="M7.72361 1.05279C7.893 1.13749 8 1.31062 8 1.5V13.5C8 13.6894 7.893 13.8625 7.72361 13.9472C7.55421 14.0319 7.35151 14.0136 7.2 13.9L3.33333 11H1.5C0.671573 11 0 10.3284 0 9.5V5.5C0 4.67158 0.671573 4 1.5 4H3.33333L7.2 1.1C7.35151 0.986371 7.55421 0.968093 7.72361 1.05279ZM7 2.5L3.8 4.9C3.71345 4.96491 3.60819 5 3.5 5H1.5C1.22386 5 1 5.22386 1 5.5V9.5C1 9.77614 1.22386 10 1.5 10H3.5C3.60819 10 3.71345 10.0351 3.8 10.1L7 12.5V2.5ZM14.8536 5.14645C15.0488 5.34171 15.0488 5.65829 14.8536 5.85355L13.2071 7.5L14.8536 9.14645C15.0488 9.34171 15.0488 9.65829 14.8536 9.85355C14.6583 10.0488 14.3417 10.0488 14.1464 9.85355L12.5 8.20711L10.8536 9.85355C10.6583 10.0488 10.3417 10.0488 10.1464 9.85355C9.95118 9.65829 9.95118 9.34171 10.1464 9.14645L11.7929 7.5L10.1464 5.85355C9.95118 5.65829 9.95118 5.34171 10.1464 5.14645C10.3417 4.95118 10.6583 4.95118 10.8536 5.14645L12.5 6.79289L14.1464 5.14645C14.3417 4.95118 14.6583 4.95118 14.8536 5.14645Z"
-    fill="currentColor"
-  />
-</svg>

crates/activity_indicator/src/activity_indicator.rs 🔗

@@ -262,7 +262,7 @@ impl ActivityIndicator {
         if !failed.is_empty() {
             return Some(Content {
                 icon: Some(
-                    Icon::new(IconName::ExclamationTriangle)
+                    Icon::new(IconName::Warning)
                         .size(IconSize::Small)
                         .into_any_element(),
                 ),
@@ -280,7 +280,7 @@ impl ActivityIndicator {
         if let Some(failure) = self.project.read(cx).last_formatting_failure() {
             return Some(Content {
                 icon: Some(
-                    Icon::new(IconName::ExclamationTriangle)
+                    Icon::new(IconName::Warning)
                         .size(IconSize::Small)
                         .into_any_element(),
                 ),
@@ -333,7 +333,7 @@ impl ActivityIndicator {
                 }),
                 AutoUpdateStatus::Errored => Some(Content {
                     icon: Some(
-                        Icon::new(IconName::ExclamationTriangle)
+                        Icon::new(IconName::Warning)
                             .size(IconSize::Small)
                             .into_any_element(),
                     ),

crates/assistant/src/assistant_panel.rs 🔗

@@ -4110,7 +4110,7 @@ impl ContextEditor {
                         h_flex()
                             .gap_3()
                             .child(
-                                Icon::new(IconName::ExclamationTriangle)
+                                Icon::new(IconName::Warning)
                                     .size(IconSize::Small)
                                     .color(Color::Warning),
                             )
@@ -5235,7 +5235,7 @@ fn quote_selection_fold_placeholder(title: String, editor: WeakView<Editor>) ->
                 ButtonLike::new(fold_id)
                     .style(ButtonStyle::Filled)
                     .layer(ElevationIndex::ElevatedSurface)
-                    .child(Icon::new(IconName::TextSelect))
+                    .child(Icon::new(IconName::CursorIBeam))
                     .child(Label::new(title.clone()).single_line())
                     .on_click(move |_, cx| {
                         editor
@@ -5339,7 +5339,7 @@ fn render_docs_slash_command_trailer(
             div()
                 .id(("latest-error", row.0))
                 .child(
-                    Icon::new(IconName::ExclamationTriangle)
+                    Icon::new(IconName::Warning)
                         .size(IconSize::Small)
                         .color(Color::Warning),
                 )

crates/assistant/src/inline_assistant.rs 🔗

@@ -1478,7 +1478,7 @@ impl Render for PromptEditor {
                     .child(
                         ModelSelector::new(
                             self.fs.clone(),
-                            IconButton::new("context", IconName::SlidersAlt)
+                            IconButton::new("context", IconName::SettingsAlt)
                                 .shape(IconButtonShape::Square)
                                 .icon_size(IconSize::Small)
                                 .icon_color(Color::Muted)

crates/assistant/src/slash_command/diagnostics_command.rs 🔗

@@ -193,11 +193,11 @@ impl SlashCommand for DiagnosticsSlashCommand {
                 .map(|(range, placeholder_type)| SlashCommandOutputSection {
                     range,
                     icon: match placeholder_type {
-                        PlaceholderType::Root(_, _) => IconName::ExclamationTriangle,
+                        PlaceholderType::Root(_, _) => IconName::Warning,
                         PlaceholderType::File(_) => IconName::File,
                         PlaceholderType::Diagnostic(DiagnosticType::Error, _) => IconName::XCircle,
                         PlaceholderType::Diagnostic(DiagnosticType::Warning, _) => {
-                            IconName::ExclamationTriangle
+                            IconName::Warning
                         }
                     },
                     label: match placeholder_type {

crates/assistant/src/terminal_inline_assistant.rs 🔗

@@ -585,7 +585,7 @@ impl Render for PromptEditor {
                     .gap_2()
                     .child(ModelSelector::new(
                         self.fs.clone(),
-                        IconButton::new("context", IconName::SlidersAlt)
+                        IconButton::new("context", IconName::SettingsAlt)
                             .shape(IconButtonShape::Square)
                             .icon_size(IconSize::Small)
                             .icon_color(Color::Muted)

crates/collab_ui/src/collab_panel.rs 🔗

@@ -2831,7 +2831,7 @@ impl Panel for CollabPanel {
     fn icon(&self, cx: &gpui::WindowContext) -> Option<ui::IconName> {
         CollaborationPanelSettings::get_global(cx)
             .button
-            .then_some(ui::IconName::Collab)
+            .then_some(ui::IconName::UserGroup)
     }
 
     fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {

crates/diagnostics/src/diagnostics.rs 🔗

@@ -667,7 +667,7 @@ impl Item for ProjectDiagnosticsEditor {
                     then.child(
                         h_flex()
                             .gap_1()
-                            .child(Icon::new(IconName::ExclamationTriangle).color(Color::Warning))
+                            .child(Icon::new(IconName::Warning).color(Color::Warning))
                             .child(
                                 Label::new(self.summary.warning_count.to_string())
                                     .color(params.text_color()),
@@ -804,7 +804,7 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
                                         icon.path(IconName::XCircle.path())
                                             .text_color(Color::Error.color(cx))
                                     } else {
-                                        icon.path(IconName::ExclamationTriangle.path())
+                                        icon.path(IconName::Warning.path())
                                             .text_color(Color::Warning.color(cx))
                                     }
                                 }),

crates/diagnostics/src/items.rs 🔗

@@ -30,7 +30,7 @@ impl Render for DiagnosticIndicator {
             (0, warning_count) => h_flex()
                 .gap_1()
                 .child(
-                    Icon::new(IconName::ExclamationTriangle)
+                    Icon::new(IconName::Warning)
                         .size(IconSize::Small)
                         .color(Color::Warning),
                 )
@@ -52,7 +52,7 @@ impl Render for DiagnosticIndicator {
                 )
                 .child(Label::new(error_count.to_string()).size(LabelSize::Small))
                 .child(
-                    Icon::new(IconName::ExclamationTriangle)
+                    Icon::new(IconName::Warning)
                         .size(IconSize::Small)
                         .color(Color::Warning),
                 )

crates/diagnostics/src/toolbar_controls.rs 🔗

@@ -50,7 +50,7 @@ impl Render for ToolbarControls {
                 )
             })
             .child(
-                IconButton::new("toggle-warnings", IconName::ExclamationTriangle)
+                IconButton::new("toggle-warnings", IconName::Warning)
                     .tooltip(move |cx| Tooltip::text(tooltip, cx))
                     .on_click(cx.listener(|this, _, cx| {
                         if let Some(editor) = this.editor() {

crates/quick_action_bar/src/quick_action_bar.rs 🔗

@@ -150,7 +150,7 @@ impl Render for QuickActionBar {
             let focus = editor.focus_handle(cx);
             PopoverMenu::new("editor-selections-dropdown")
                 .trigger(
-                    IconButton::new("toggle_editor_selections_icon", IconName::TextCursor)
+                    IconButton::new("toggle_editor_selections_icon", IconName::CursorIBeam)
                         .shape(IconButtonShape::Square)
                         .icon_size(IconSize::Small)
                         .style(ButtonStyle::Subtle)

crates/terminal_view/src/terminal_view.rs 🔗

@@ -991,7 +991,7 @@ impl Item for TerminalView {
             Some(terminal_task) => match &terminal_task.status {
                 TaskStatus::Running => (IconName::Play, Color::Disabled, None),
                 TaskStatus::Unknown => (
-                    IconName::ExclamationTriangle,
+                    IconName::Warning,
                     Color::Warning,
                     Some(rerun_button(terminal_task.id.clone())),
                 ),

crates/ui/src/components/icon.rs 🔗

@@ -1,6 +1,7 @@
 use gpui::{svg, AnimationElement, Hsla, IntoElement, Rems, Transformation};
 use serde::{Deserialize, Serialize};
 use strum::{EnumIter, EnumString, IntoStaticStr};
+use ui_macros::DerivePathStr;
 
 use crate::{prelude::*, Indicator};
 
@@ -102,15 +103,27 @@ impl IconSize {
 }
 
 #[derive(
-    Debug, PartialEq, Eq, Copy, Clone, EnumIter, EnumString, IntoStaticStr, Serialize, Deserialize,
+    Debug,
+    PartialEq,
+    Eq,
+    Copy,
+    Clone,
+    EnumIter,
+    EnumString,
+    IntoStaticStr,
+    Serialize,
+    Deserialize,
+    DerivePathStr,
 )]
+#[strum(serialize_all = "snake_case")]
+#[path_str(prefix = "icons", suffix = ".svg")]
 pub enum IconName {
     Ai,
     AiAnthropic,
     AiAnthropicHosted,
-    AiOpenAi,
     AiGoogle,
     AiOllama,
+    AiOpenAi,
     AiZed,
     ArrowCircle,
     ArrowDown,
@@ -135,15 +148,13 @@ pub enum IconName {
     CaseSensitive,
     Check,
     ChevronDown,
-    /// This chevron indicates a popover menu.
-    ChevronDownSmall,
+    ChevronDownSmall, // This chevron indicates a popover menu.
     ChevronLeft,
     ChevronRight,
     ChevronUp,
     ChevronUpDown,
     Close,
     Code,
-    Collab,
     Command,
     Context,
     Control,
@@ -153,6 +164,8 @@ pub enum IconName {
     CopilotInit,
     Copy,
     CountdownTimer,
+    CursorIBeam,
+    CursorText,
     Dash,
     DatabaseZap,
     Delete,
@@ -162,21 +175,20 @@ pub enum IconName {
     EllipsisVertical,
     Envelope,
     Escape,
-    ExclamationTriangle,
     Exit,
     ExpandVertical,
     ExternalLink,
     Eye,
     File,
+    FileCode,
     FileDoc,
     FileGeneric,
     FileGit,
     FileLock,
     FileRust,
+    FileText,
     FileToml,
     FileTree,
-    FileText,
-    FileCode,
     Filter,
     Folder,
     FolderOpen,
@@ -184,11 +196,11 @@ pub enum IconName {
     Font,
     FontSize,
     FontWeight,
-    Github,
-    GenericMinimize,
-    GenericMaximize,
     GenericClose,
+    GenericMaximize,
+    GenericMinimize,
     GenericRestore,
+    Github,
     Hash,
     HistoryRerun,
     Indicator,
@@ -228,21 +240,21 @@ pub enum IconName {
     Rerun,
     Return,
     Reveal,
-    Route,
     RotateCcw,
     RotateCw,
+    Route,
     Save,
     Screen,
-    SearchSelection,
     SearchCode,
+    SearchSelection,
     SelectAll,
     Server,
     Settings,
+    SettingsAlt,
     Shift,
     Slash,
     SlashSquare,
     Sliders,
-    SlidersAlt,
     Snip,
     Space,
     Sparkle,
@@ -260,191 +272,18 @@ pub enum IconName {
     SupermavenInit,
     Tab,
     Terminal,
-    TextCursor,
-    TextSelect,
     Trash,
     TriangleRight,
     Undo,
     Unpin,
     Update,
+    UserGroup,
+    Visible,
+    Warning,
     WholeWord,
     XCircle,
     ZedAssistant,
     ZedAssistantFilled,
-    Visible,
-}
-
-impl IconName {
-    pub fn path(self) -> &'static str {
-        match self {
-            IconName::Ai => "icons/ai.svg",
-            IconName::AiAnthropic => "icons/ai_anthropic.svg",
-            IconName::AiAnthropicHosted => "icons/ai_anthropic_hosted.svg",
-            IconName::AiOpenAi => "icons/ai_open_ai.svg",
-            IconName::AiGoogle => "icons/ai_google.svg",
-            IconName::AiOllama => "icons/ai_ollama.svg",
-            IconName::AiZed => "icons/ai_zed.svg",
-            IconName::ArrowCircle => "icons/arrow_circle.svg",
-            IconName::ArrowDown => "icons/arrow_down.svg",
-            IconName::ArrowDownFromLine => "icons/arrow_down_from_line.svg",
-            IconName::ArrowLeft => "icons/arrow_left.svg",
-            IconName::ArrowRight => "icons/arrow_right.svg",
-            IconName::ArrowUp => "icons/arrow_up.svg",
-            IconName::ArrowUpFromLine => "icons/arrow_up_from_line.svg",
-            IconName::ArrowUpRight => "icons/arrow_up_right.svg",
-            IconName::AtSign => "icons/at_sign.svg",
-            IconName::AudioOff => "icons/speaker_off.svg",
-            IconName::AudioOn => "icons/speaker_loud.svg",
-            IconName::Backspace => "icons/backspace.svg",
-            IconName::Bell => "icons/bell.svg",
-            IconName::BellDot => "icons/bell_dot.svg",
-            IconName::BellOff => "icons/bell_off.svg",
-            IconName::BellRing => "icons/bell_ring.svg",
-            IconName::Bolt => "icons/bolt.svg",
-            IconName::Book => "icons/book.svg",
-            IconName::BookCopy => "icons/book_copy.svg",
-            IconName::BookPlus => "icons/book_plus.svg",
-            IconName::CaseSensitive => "icons/case_insensitive.svg",
-            IconName::Check => "icons/check.svg",
-            IconName::ChevronDown => "icons/chevron_down.svg",
-            IconName::ChevronDownSmall => "icons/chevron_down_small.svg",
-            IconName::ChevronLeft => "icons/chevron_left.svg",
-            IconName::ChevronRight => "icons/chevron_right.svg",
-            IconName::ChevronUp => "icons/chevron_up.svg",
-            IconName::ChevronUpDown => "icons/chevron_up_down.svg",
-            IconName::Close => "icons/x.svg",
-            IconName::Code => "icons/code.svg",
-            IconName::Collab => "icons/user_group_16.svg",
-            IconName::Command => "icons/command.svg",
-            IconName::Context => "icons/context.svg",
-            IconName::Control => "icons/control.svg",
-            IconName::Copilot => "icons/copilot.svg",
-            IconName::CopilotDisabled => "icons/copilot_disabled.svg",
-            IconName::CopilotError => "icons/copilot_error.svg",
-            IconName::CopilotInit => "icons/copilot_init.svg",
-            IconName::Copy => "icons/copy.svg",
-            IconName::CountdownTimer => "icons/countdown_timer.svg",
-            IconName::Dash => "icons/dash.svg",
-            IconName::DatabaseZap => "icons/database_zap.svg",
-            IconName::Delete => "icons/delete.svg",
-            IconName::Disconnected => "icons/disconnected.svg",
-            IconName::Download => "icons/download.svg",
-            IconName::Ellipsis => "icons/ellipsis.svg",
-            IconName::EllipsisVertical => "icons/ellipsis_vertical.svg",
-            IconName::Envelope => "icons/feedback.svg",
-            IconName::Escape => "icons/escape.svg",
-            IconName::ExclamationTriangle => "icons/warning.svg",
-            IconName::Exit => "icons/exit.svg",
-            IconName::ExpandVertical => "icons/expand_vertical.svg",
-            IconName::ExternalLink => "icons/external_link.svg",
-            IconName::Eye => "icons/eye.svg",
-            IconName::File => "icons/file.svg",
-            IconName::FileDoc => "icons/file_icons/book.svg",
-            IconName::FileGeneric => "icons/file_icons/file.svg",
-            IconName::FileGit => "icons/file_icons/git.svg",
-            IconName::FileLock => "icons/file_icons/lock.svg",
-            IconName::FileRust => "icons/file_icons/rust.svg",
-            IconName::FileToml => "icons/file_icons/toml.svg",
-            IconName::FileTree => "icons/project.svg",
-            IconName::FileCode => "icons/file_code.svg",
-            IconName::FileText => "icons/file_text.svg",
-            IconName::Filter => "icons/filter.svg",
-            IconName::Folder => "icons/file_icons/folder.svg",
-            IconName::FolderOpen => "icons/file_icons/folder_open.svg",
-            IconName::FolderX => "icons/stop_sharing.svg",
-            IconName::Font => "icons/font.svg",
-            IconName::FontSize => "icons/font_size.svg",
-            IconName::FontWeight => "icons/font_weight.svg",
-            IconName::Github => "icons/github.svg",
-            IconName::GenericMinimize => "icons/generic_minimize.svg",
-            IconName::GenericMaximize => "icons/generic_maximize.svg",
-            IconName::GenericClose => "icons/generic_close.svg",
-            IconName::GenericRestore => "icons/generic_restore.svg",
-            IconName::Hash => "icons/hash.svg",
-            IconName::HistoryRerun => "icons/history_rerun.svg",
-            IconName::Indicator => "icons/indicator.svg",
-            IconName::IndicatorX => "icons/indicator_x.svg",
-            IconName::InlayHint => "icons/inlay_hint.svg",
-            IconName::Library => "icons/library.svg",
-            IconName::LineHeight => "icons/line_height.svg",
-            IconName::Link => "icons/link.svg",
-            IconName::ListTree => "icons/list_tree.svg",
-            IconName::MagnifyingGlass => "icons/magnifying_glass.svg",
-            IconName::MailOpen => "icons/mail_open.svg",
-            IconName::Maximize => "icons/maximize.svg",
-            IconName::Menu => "icons/menu.svg",
-            IconName::MessageBubbles => "icons/conversations.svg",
-            IconName::Mic => "icons/mic.svg",
-            IconName::MicMute => "icons/mic_mute.svg",
-            IconName::Microscope => "icons/microscope.svg",
-            IconName::Minimize => "icons/minimize.svg",
-            IconName::Option => "icons/option.svg",
-            IconName::PageDown => "icons/page_down.svg",
-            IconName::PageUp => "icons/page_up.svg",
-            IconName::Pencil => "icons/pencil.svg",
-            IconName::Person => "icons/person.svg",
-            IconName::Pin => "icons/pin.svg",
-            IconName::Play => "icons/play.svg",
-            IconName::Plus => "icons/plus.svg",
-            IconName::PocketKnife => "icons/pocket_knife.svg",
-            IconName::Public => "icons/public.svg",
-            IconName::PullRequest => "icons/pull_request.svg",
-            IconName::Quote => "icons/quote.svg",
-            IconName::Regex => "icons/regex.svg",
-            IconName::ReplNeutral => "icons/repl_neutral.svg",
-            IconName::Replace => "icons/replace.svg",
-            IconName::ReplaceAll => "icons/replace_all.svg",
-            IconName::ReplaceNext => "icons/replace_next.svg",
-            IconName::ReplyArrowRight => "icons/reply_arrow_right.svg",
-            IconName::Rerun => "icons/rerun.svg",
-            IconName::Return => "icons/return.svg",
-            IconName::Reveal => "icons/reveal.svg",
-            IconName::RotateCcw => "icons/rotate_ccw.svg",
-            IconName::RotateCw => "icons/rotate_cw.svg",
-            IconName::Route => "icons/route.svg",
-            IconName::Save => "icons/save.svg",
-            IconName::Screen => "icons/desktop.svg",
-            IconName::SearchSelection => "icons/search_selection.svg",
-            IconName::SearchCode => "icons/search_code.svg",
-            IconName::SelectAll => "icons/select_all.svg",
-            IconName::Server => "icons/server.svg",
-            IconName::Settings => "icons/file_icons/settings.svg",
-            IconName::Shift => "icons/shift.svg",
-            IconName::Slash => "icons/slash.svg",
-            IconName::SlashSquare => "icons/slash_square.svg",
-            IconName::Sliders => "icons/sliders.svg",
-            IconName::SlidersAlt => "icons/sliders-alt.svg",
-            IconName::Snip => "icons/snip.svg",
-            IconName::Space => "icons/space.svg",
-            IconName::Sparkle => "icons/sparkle.svg",
-            IconName::SparkleAlt => "icons/sparkle_alt.svg",
-            IconName::SparkleFilled => "icons/sparkle_filled.svg",
-            IconName::Spinner => "icons/spinner.svg",
-            IconName::Split => "icons/split.svg",
-            IconName::Star => "icons/star.svg",
-            IconName::StarFilled => "icons/star_filled.svg",
-            IconName::Stop => "icons/stop.svg",
-            IconName::Strikethrough => "icons/strikethrough.svg",
-            IconName::Supermaven => "icons/supermaven.svg",
-            IconName::SupermavenDisabled => "icons/supermaven_disabled.svg",
-            IconName::SupermavenError => "icons/supermaven_error.svg",
-            IconName::SupermavenInit => "icons/supermaven_init.svg",
-            IconName::Tab => "icons/tab.svg",
-            IconName::Terminal => "icons/terminal.svg",
-            IconName::TextCursor => "icons/text-cursor.svg",
-            IconName::TextSelect => "icons/text_select.svg",
-            IconName::Trash => "icons/trash.svg",
-            IconName::TriangleRight => "icons/triangle_right.svg",
-            IconName::Unpin => "icons/unpin.svg",
-            IconName::Update => "icons/update.svg",
-            IconName::Undo => "icons/undo.svg",
-            IconName::WholeWord => "icons/word_search.svg",
-            IconName::XCircle => "icons/error.svg",
-            IconName::ZedAssistant => "icons/zed_assistant.svg",
-            IconName::ZedAssistantFilled => "icons/zed_assistant_filled.svg",
-            IconName::Visible => "icons/visible.svg",
-        }
-    }
 }
 
 #[derive(IntoElement)]

crates/ui/src/components/stories/list_header.rs 🔗

@@ -24,7 +24,7 @@ impl Render for ListHeaderStory {
             .child(
                 ListHeader::new("Section 4")
                     .end_slot(IconButton::new("action_1", IconName::Bolt))
-                    .end_slot(IconButton::new("action_2", IconName::ExclamationTriangle))
+                    .end_slot(IconButton::new("action_2", IconName::Warning))
                     .end_slot(IconButton::new("action_3", IconName::Plus)),
             )
     }

crates/workspace/src/notifications.rs 🔗

@@ -311,15 +311,11 @@ impl Render for LanguageServerPrompt {
                                                 .mt(px(-2.0))
                                                 .map(|icon| {
                                                     if severity == DiagnosticSeverity::ERROR {
-                                                        icon.path(
-                                                            IconName::ExclamationTriangle.path(),
-                                                        )
-                                                        .text_color(Color::Error.color(cx))
+                                                        icon.path(IconName::Warning.path())
+                                                            .text_color(Color::Error.color(cx))
                                                     } else {
-                                                        icon.path(
-                                                            IconName::ExclamationTriangle.path(),
-                                                        )
-                                                        .text_color(Color::Warning.color(cx))
+                                                        icon.path(IconName::Warning.path())
+                                                            .text_color(Color::Warning.color(cx))
                                                     }
                                                 })
                                         }),
@@ -421,7 +417,7 @@ impl Render for ErrorMessagePrompt {
                                     .mr_2()
                                     .mt(px(-2.0))
                                     .map(|icon| {
-                                        icon.path(IconName::ExclamationTriangle.path())
+                                        icon.path(IconName::Warning.path())
                                             .text_color(Color::Error.color(cx))
                                     }),
                             )