Foundations / Assets
Icons
Markdown crates/icons/src/lib.rs docs.rs
use ui::icons::{self, Icon, glyph};
use ui::widgets::Icons;
theme.icon(glyph::Search) // the ladder's body step, in the text tone
theme.icon_at(TextStyle::Caption, glyph::Search) // another rung
icons::icon(glyph::Search).size(px(16.0)).text_color(theme.text_muted)gpui resolves an svg's tone from that element's own style and never inherits one, so icons::icon(..) with no text_color anywhere paints nothing — no warning, no fallback. theme.icon is the same builder with the size and tone already in it.
Sources
theme.row_icon(glyph::Monitor) // a glyph compiled in
theme.row_icon(Icon::asset("brand/mark.svg")) // the app's own AssetSource
theme.row_icon(Icon::file(picked)) // a file on diskEvery component takes impl Into<Icon>, so a constant passes as itself and the component never learns which kind it got.
Solid twins
theme.icon(Icon::glyph(glyph::Star).solid())
icons::solid(glyph::Star) // the same, for the common caseA property of the value rather than a second call, so a control can hold one Icon and flip the variant instead of branching between two functions.
Features
bezel-icons = { version = "0.1", features = ["arrows", "navigation"] }One per Lucide category, named as Lucide names them; full is all 42, and nothing is on by default. Cargo unions features across a graph, so ui's own three — arrows, notifications, text — are the floor for anything depending on it.
API
pub trait Icons: ThemeExt {
/// Returns a gpui `Svg`, so a `Styled` call after it wins — the tone is a
/// floor, not a decision.
fn icon(&self, icon: impl Into<Icon>) -> Svg;
/// Another rung of the ladder.
fn icon_at(&self, role: TextStyle, icon: impl Into<Icon>) -> Svg;
}// icons — an `Icon` carries no size and no colour: those belong to the
// component painting it.
impl Icon {
pub const fn glyph(svg: &'static [u8]) -> Self;
/// Resolved through the app's registered `AssetSource`.
pub fn asset(key: impl Into<SharedString>) -> Self;
/// Loaded off the paint thread and cached, so the first frame or two paint
/// nothing.
pub fn file(path: impl Into<SharedString>) -> Self;
/// Fills the outline — filled *and* stroked, so the outer edge lands where
/// the outline puts it and a control swapping between them does not jump.
pub fn solid(self) -> Self;
// ...
}
/// The bare builder: it carries no tone, so it needs one set on the glyph.
pub fn icon(icon: impl Into<Icon>) -> Svg;
pub fn solid(icon: impl Into<Icon>) -> Svg;
/// Every enabled category and its `(name, svg)` pairs, for an icon browser.
/// Naming it pins the whole enabled set.
pub const CATEGORIES: &[(&str, &[(&str, Icon)])];An Icon carries no size and no colour: those belong to the component. Modules and constants are Lucide's own, generated by crates/icons/build.rs from a pinned release — bumping the version is the upgrade, and the diff says which glyphs upstream redrew. Lucide is ISC-licensed and asks for no attribution in a shipped binary.