Add `icons` crate (#27447)

Marshall Bowers created

This PR adds a new `icons` crate and moves the `IconName` into it.

We have a number of crates that are taking a dependency on `ui` just so
they can talk about icons, which is not ideal.

Release Notes:

- N/A

Change summary

Cargo.lock                       |   9 +
Cargo.toml                       |   2 
crates/icons/Cargo.toml          |  16 ++
crates/icons/LICENSE-GPL         |   1 
crates/icons/src/icons.rs        | 248 +++++++++++++++++++++++++++++++++
crates/ui/Cargo.toml             |   3 
crates/ui/src/components/icon.rs | 251 ---------------------------------
7 files changed, 279 insertions(+), 251 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -6490,6 +6490,14 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "icons"
+version = "0.1.0"
+dependencies = [
+ "serde",
+ "strum",
+]
+
 [[package]]
 name = "icu_collections"
 version = "1.5.0"
@@ -14928,6 +14936,7 @@ dependencies = [
  "chrono",
  "component",
  "gpui",
+ "icons",
  "itertools 0.14.0",
  "linkme",
  "menu",

Cargo.toml 🔗

@@ -70,6 +70,7 @@ members = [
     "crates/html_to_markdown",
     "crates/http_client",
     "crates/http_client_tls",
+    "crates/icons",
     "crates/image_viewer",
     "crates/indexed_docs",
     "crates/inline_completion",
@@ -274,6 +275,7 @@ gpui_tokio = { path = "crates/gpui_tokio" }
 html_to_markdown = { path = "crates/html_to_markdown" }
 http_client = { path = "crates/http_client" }
 http_client_tls = { path = "crates/http_client_tls" }
+icons = { path = "crates/icons" }
 image_viewer = { path = "crates/image_viewer" }
 indexed_docs = { path = "crates/indexed_docs" }
 inline_completion = { path = "crates/inline_completion" }

crates/icons/Cargo.toml 🔗

@@ -0,0 +1,16 @@
+[package]
+name = "icons"
+version = "0.1.0"
+edition.workspace = true
+publish.workspace = true
+license = "GPL-3.0-or-later"
+
+[lints]
+workspace = true
+
+[lib]
+path = "src/icons.rs"
+
+[dependencies]
+serde.workspace = true
+strum.workspace = true

crates/icons/src/icons.rs 🔗

@@ -0,0 +1,248 @@
+use std::sync::Arc;
+
+use serde::{Deserialize, Serialize};
+use strum::{EnumIter, EnumString, IntoStaticStr};
+
+#[derive(
+    Debug, PartialEq, Eq, Copy, Clone, EnumIter, EnumString, IntoStaticStr, Serialize, Deserialize,
+)]
+#[strum(serialize_all = "snake_case")]
+pub enum IconName {
+    Ai,
+    AiAnthropic,
+    AiBedrock,
+    AiAnthropicHosted,
+    AiDeepSeek,
+    AiEdit,
+    AiGoogle,
+    AiLmStudio,
+    AiMistral,
+    AiOllama,
+    AiOpenAi,
+    AiZed,
+    ArrowCircle,
+    ArrowDown,
+    ArrowDownFromLine,
+    ArrowLeft,
+    ArrowRight,
+    ArrowRightLeft,
+    ArrowUp,
+    ArrowUpFromLine,
+    ArrowUpRight,
+    ArrowUpRightAlt,
+    AtSign,
+    AudioOff,
+    AudioOn,
+    Backspace,
+    Bell,
+    BellDot,
+    BellOff,
+    BellRing,
+    Blocks,
+    Bolt,
+    Book,
+    BookCopy,
+    BookPlus,
+    Brain,
+    CaseSensitive,
+    Check,
+    ChevronDown,
+    /// This chevron indicates a popover menu.
+    ChevronDownSmall,
+    ChevronLeft,
+    ChevronRight,
+    ChevronUp,
+    ChevronUpDown,
+    Circle,
+    Clipboard,
+    Close,
+    Code,
+    Cog,
+    Command,
+    Context,
+    Control,
+    Copilot,
+    CopilotDisabled,
+    CopilotError,
+    CopilotInit,
+    Copy,
+    CountdownTimer,
+    CursorIBeam,
+    Dash,
+    DebugBreakpoint,
+    DebugIgnoreBreakpoints,
+    DebugPause,
+    DebugContinue,
+    DebugStepOver,
+    DebugStepInto,
+    DebugStepOut,
+    DebugStepBack,
+    DebugRestart,
+    Debug,
+    DebugStop,
+    DebugDisconnect,
+    DebugLogBreakpoint,
+    DatabaseZap,
+    Delete,
+    Diff,
+    Disconnected,
+    Download,
+    Ellipsis,
+    EllipsisVertical,
+    Envelope,
+    Eraser,
+    Escape,
+    ExpandVertical,
+    Exit,
+    ExternalLink,
+    ExpandUp,
+    ExpandDown,
+    Eye,
+    File,
+    FileCode,
+    FileDoc,
+    FileDiff,
+    FileGeneric,
+    FileGit,
+    FileLock,
+    FileRust,
+    FileSearch,
+    FileText,
+    FileToml,
+    FileTree,
+    Filter,
+    Folder,
+    FolderOpen,
+    FolderX,
+    Font,
+    FontSize,
+    FontWeight,
+    GenericClose,
+    GenericMaximize,
+    GenericMinimize,
+    GenericRestore,
+    Github,
+    Globe,
+    GitBranch,
+    GitBranchSmall,
+    Hash,
+    HistoryRerun,
+    Indicator,
+    Info,
+    InlayHint,
+    Keyboard,
+    Library,
+    LineHeight,
+    Link,
+    ListTree,
+    ListX,
+    LockOutlined,
+    MagnifyingGlass,
+    MailOpen,
+    Maximize,
+    Menu,
+    MessageBubbles,
+    MessageCircle,
+    Cloud,
+    Mic,
+    MicMute,
+    Microscope,
+    Minimize,
+    Option,
+    PageDown,
+    PageUp,
+    PanelLeft,
+    PanelRight,
+    Pencil,
+    Person,
+    PersonCircle,
+    PhoneIncoming,
+    Pin,
+    Play,
+    Plus,
+    PocketKnife,
+    Public,
+    PullRequest,
+    Quote,
+    RefreshTitle,
+    Regex,
+    ReplNeutral,
+    Replace,
+    ReplaceAll,
+    ReplaceNext,
+    ReplyArrowRight,
+    Rerun,
+    Return,
+    Reveal,
+    RotateCcw,
+    RotateCw,
+    Route,
+    Save,
+    Screen,
+    SearchCode,
+    SearchSelection,
+    SelectAll,
+    Server,
+    Settings,
+    SettingsAlt,
+    Shift,
+    Slash,
+    SlashSquare,
+    Sliders,
+    SlidersVertical,
+    Snip,
+    Space,
+    Sparkle,
+    SparkleAlt,
+    SparkleFilled,
+    Spinner,
+    Split,
+    SquareDot,
+    SquareMinus,
+    SquarePlus,
+    Star,
+    StarFilled,
+    Stop,
+    Strikethrough,
+    Supermaven,
+    SupermavenDisabled,
+    SupermavenError,
+    SupermavenInit,
+    SwatchBook,
+    Tab,
+    Terminal,
+    TextSnippet,
+    ThumbsUp,
+    ThumbsDown,
+    Trash,
+    TrashAlt,
+    Triangle,
+    TriangleRight,
+    Undo,
+    Unpin,
+    Update,
+    UserGroup,
+    Visible,
+    Wand,
+    Warning,
+    WholeWord,
+    X,
+    XCircle,
+    ZedAssistant,
+    ZedAssistant2,
+    ZedAssistantFilled,
+    ZedPredict,
+    ZedPredictUp,
+    ZedPredictDown,
+    ZedPredictDisabled,
+    ZedPredictError,
+    ZedXCopilot,
+}
+
+impl IconName {
+    /// Returns the path to this icon.
+    pub fn path(&self) -> Arc<str> {
+        let file_stem: &'static str = self.into();
+        format!("icons/{file_stem}.svg").into()
+    }
+}

crates/ui/Cargo.toml 🔗

@@ -16,6 +16,7 @@ path = "src/ui.rs"
 chrono.workspace = true
 component.workspace = true
 gpui.workspace = true
+icons.workspace = true
 itertools.workspace = true
 linkme.workspace = true
 menu.workspace = true
@@ -23,7 +24,7 @@ serde.workspace = true
 settings.workspace = true
 smallvec.workspace = true
 story = { workspace = true, optional = true }
-strum = { workspace = true, features = ["derive"] }
+strum.workspace = true
 theme.workspace = true
 ui_macros.workspace = true
 util.workspace = true

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

@@ -7,9 +7,7 @@ use std::sync::Arc;
 pub use decorated_icon::*;
 use gpui::{img, svg, AnimationElement, AnyElement, Hsla, IntoElement, Rems, Transformation};
 pub use icon_decoration::*;
-use serde::{Deserialize, Serialize};
-use strum::{EnumIter, EnumString, IntoStaticStr};
-use ui_macros::DerivePathStr;
+pub use icons::*;
 
 use crate::{prelude::*, Indicator};
 
@@ -107,253 +105,6 @@ impl IconSize {
     }
 }
 
-#[derive(
-    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,
-    AiBedrock,
-    AiAnthropicHosted,
-    AiDeepSeek,
-    AiEdit,
-    AiGoogle,
-    AiLmStudio,
-    AiMistral,
-    AiOllama,
-    AiOpenAi,
-    AiZed,
-    ArrowCircle,
-    ArrowDown,
-    ArrowDownFromLine,
-    ArrowLeft,
-    ArrowRight,
-    ArrowRightLeft,
-    ArrowUp,
-    ArrowUpFromLine,
-    ArrowUpRight,
-    ArrowUpRightAlt,
-    AtSign,
-    AudioOff,
-    AudioOn,
-    Backspace,
-    Bell,
-    BellDot,
-    BellOff,
-    BellRing,
-    Blocks,
-    Bolt,
-    Book,
-    BookCopy,
-    BookPlus,
-    Brain,
-    CaseSensitive,
-    Check,
-    ChevronDown,
-    /// This chevron indicates a popover menu.
-    ChevronDownSmall,
-    ChevronLeft,
-    ChevronRight,
-    ChevronUp,
-    ChevronUpDown,
-    Circle,
-    Clipboard,
-    Close,
-    Code,
-    Cog,
-    Command,
-    Context,
-    Control,
-    Copilot,
-    CopilotDisabled,
-    CopilotError,
-    CopilotInit,
-    Copy,
-    CountdownTimer,
-    CursorIBeam,
-    Dash,
-    DebugBreakpoint,
-    DebugIgnoreBreakpoints,
-    DebugPause,
-    DebugContinue,
-    DebugStepOver,
-    DebugStepInto,
-    DebugStepOut,
-    DebugStepBack,
-    DebugRestart,
-    Debug,
-    DebugStop,
-    DebugDisconnect,
-    DebugLogBreakpoint,
-    DatabaseZap,
-    Delete,
-    Diff,
-    Disconnected,
-    Download,
-    Ellipsis,
-    EllipsisVertical,
-    Envelope,
-    Eraser,
-    Escape,
-    ExpandVertical,
-    Exit,
-    ExternalLink,
-    ExpandUp,
-    ExpandDown,
-    Eye,
-    File,
-    FileCode,
-    FileDoc,
-    FileDiff,
-    FileGeneric,
-    FileGit,
-    FileLock,
-    FileRust,
-    FileSearch,
-    FileText,
-    FileToml,
-    FileTree,
-    Filter,
-    Folder,
-    FolderOpen,
-    FolderX,
-    Font,
-    FontSize,
-    FontWeight,
-    GenericClose,
-    GenericMaximize,
-    GenericMinimize,
-    GenericRestore,
-    Github,
-    Globe,
-    GitBranch,
-    GitBranchSmall,
-    Hash,
-    HistoryRerun,
-    Indicator,
-    Info,
-    InlayHint,
-    Keyboard,
-    Library,
-    LineHeight,
-    Link,
-    ListTree,
-    ListX,
-    LockOutlined,
-    MagnifyingGlass,
-    MailOpen,
-    Maximize,
-    Menu,
-    MessageBubbles,
-    MessageCircle,
-    Cloud,
-    Mic,
-    MicMute,
-    Microscope,
-    Minimize,
-    Option,
-    PageDown,
-    PageUp,
-    PanelLeft,
-    PanelRight,
-    Pencil,
-    Person,
-    PersonCircle,
-    PhoneIncoming,
-    Pin,
-    Play,
-    Plus,
-    PocketKnife,
-    Public,
-    PullRequest,
-    Quote,
-    RefreshTitle,
-    Regex,
-    ReplNeutral,
-    Replace,
-    ReplaceAll,
-    ReplaceNext,
-    ReplyArrowRight,
-    Rerun,
-    Return,
-    Reveal,
-    RotateCcw,
-    RotateCw,
-    Route,
-    Save,
-    Screen,
-    SearchCode,
-    SearchSelection,
-    SelectAll,
-    Server,
-    Settings,
-    SettingsAlt,
-    Shift,
-    Slash,
-    SlashSquare,
-    Sliders,
-    SlidersVertical,
-    Snip,
-    Space,
-    Sparkle,
-    SparkleAlt,
-    SparkleFilled,
-    Spinner,
-    Split,
-    SquareDot,
-    SquareMinus,
-    SquarePlus,
-    Star,
-    StarFilled,
-    Stop,
-    Strikethrough,
-    Supermaven,
-    SupermavenDisabled,
-    SupermavenError,
-    SupermavenInit,
-    SwatchBook,
-    Tab,
-    Terminal,
-    TextSnippet,
-    ThumbsUp,
-    ThumbsDown,
-    Trash,
-    TrashAlt,
-    Triangle,
-    TriangleRight,
-    Undo,
-    Unpin,
-    Update,
-    UserGroup,
-    Visible,
-    Wand,
-    Warning,
-    WholeWord,
-    X,
-    XCircle,
-    ZedAssistant,
-    ZedAssistant2,
-    ZedAssistantFilled,
-    ZedPredict,
-    ZedPredictUp,
-    ZedPredictDown,
-    ZedPredictDisabled,
-    ZedPredictError,
-    ZedXCopilot,
-}
-
 impl From<IconName> for Icon {
     fn from(icon: IconName) -> Self {
         Icon::new(icon)