egui_phosphor_icons/
lib.rs

1//! # egui_phosphor_icons
2//!
3//! A Rust library providing [Phosphor Icons](https://phosphoricons.com/) for [egui](https://github.com/emilk/egui).
4//!
5//! ## Features
6//!
7//! - **Multiple font styles**: Regular, Bold, Fill, Light, and Thin variants
8//! - **Feature flags**: Control which font styles are included to reduce binary size
9//! - **String lookup**: Look up icons by name for serialization/configuration support
10//!
11//! ## Quick Start
12//!
13//! ```no_run
14//! use egui_phosphor_icons::{add_fonts, icons, Icon};
15//! # fn setup_fonts(ctx: &egui::Context) {
16//!
17//! // Setup fonts (call once during initialization)
18//! let mut fonts = egui::FontDefinitions::default();
19//! add_fonts(&mut fonts);
20//! ctx.set_fonts(fonts);
21//! # }
22//! # fn ui_example(ui: &mut egui::Ui) {
23//!
24//! // Use icons in your UI
25//! ui.label(icons::HOUSE);              // Regular style (default)
26//! ui.label(icons::HOUSE.bold());       // Bold style
27//! ui.label(icons::HOUSE.fill());       // Fill style
28//! ui.label(icons::HOUSE.light());      // Light style
29//! ui.label(icons::HOUSE.thin());       // Thin style
30//!
31//! // Chain with RichText methods
32//! ui.label(icons::HEART.fill().color(egui::Color32::RED).size(32.0));
33//!
34//! // Look up icons by string name (kebab-case)
35//! if let Some(icon) = Icon::from_name("arrow-up-left") {
36//!     ui.label(icon.regular());
37//! }
38//! # }
39//! ```
40//!
41//! ## Feature Flags
42//!
43//! By default, all font styles are included. You can disable specific styles to reduce binary size:
44//!
45//! ```toml
46//! # Only include regular and bold styles
47//! egui_phosphor_icons = { version = "0.1.0", default-features = false, features = ["bold"] }
48//!
49//! # Only regular style (smallest binary size)
50//! egui_phosphor_icons = { version = "0.1.0", default-features = false }
51//! ```
52//!
53//! Available features:
54//! - `bold` - Bold font variant
55//! - `fill` - Fill font variant
56//! - `light` - Light font variant
57//! - `thin` - Thin font variant
58//!
59//! ## Usage with bevy_egui
60//!
61//! When using this library with [bevy_egui](https://github.com/mvlabat/bevy_egui), configure fonts during initialization:
62//!
63//! ```ignore
64//! use bevy::prelude::*;
65//! use bevy_egui::{EguiContext, EguiPlugin, PrimaryEguiContext, egui};
66//! use egui_phosphor_icons::{add_fonts, icons};
67//!
68//! fn main() {
69//!     App::new()
70//!         .add_plugins(DefaultPlugins)
71//!         .add_plugins(EguiPlugin)
72//!         .add_systems(Update, configure_fonts)
73//!         .run();
74//! }
75//!
76//! // Configure fonts once when EguiContext is first added
77//! fn configure_fonts(mut egui_contexts: Query<&mut EguiContext, Added<PrimaryEguiContext>>) {
78//!     let Some(mut ctx) = egui_contexts.iter_mut().next() else {
79//!         return;
80//!     };
81//!
82//!     let mut fonts = egui::FontDefinitions::default();
83//!     add_fonts(&mut fonts);
84//!     ctx.get_mut().set_fonts(fonts);
85//! }
86//! ```
87
88pub mod icons;
89
90use std::sync::Arc;
91
92// Font family name constants - used internally
93const PHOSPHOR_REGULAR_NAME: &str = "phosphor-regular";
94
95#[cfg(feature = "bold")]
96const PHOSPHOR_BOLD_NAME: &str = "phosphor-bold";
97
98#[cfg(feature = "fill")]
99const PHOSPHOR_FILL_NAME: &str = "phosphor-fill";
100
101#[cfg(feature = "light")]
102const PHOSPHOR_LIGHT_NAME: &str = "phosphor-light";
103
104#[cfg(feature = "thin")]
105const PHOSPHOR_THIN_NAME: &str = "phosphor-thin";
106
107/// Adds Phosphor Icons font to egui font definitions.
108///
109/// This function loads the Phosphor Icons font and creates separate font families
110/// for each variant, allowing you to choose which style to use when rendering icons.
111///
112/// # Example
113/// ```no_run
114/// use egui_phosphor_icons::{add_fonts, icons};
115/// # fn setup_fonts(ctx: &egui::Context) {
116///
117/// let mut fonts = egui::FontDefinitions::default();
118/// add_fonts(&mut fonts);
119/// // Then set the fonts on your context:
120/// ctx.set_fonts(fonts);
121/// # }
122/// # fn ui_example(ui: &mut egui::Ui) {
123///
124/// // Use icons with different styles:
125/// ui.label(icons::HOUSE.regular());
126/// ui.label(icons::HOUSE.bold());  // Requires "bold" feature
127/// ui.label(icons::HOUSE.fill());  // Requires "fill" feature
128/// # }
129/// ```
130pub fn add_fonts(fonts: &mut egui::FontDefinitions) {
131    // Load phosphor icons fonts (regular is always included)
132    let phosphor_font_data = include_bytes!("../assets/fonts/Phosphor.ttf");
133    fonts.font_data.insert(
134        "phosphor-icons".to_owned(),
135        Arc::new(egui::FontData::from_static(phosphor_font_data)),
136    );
137
138    #[cfg(feature = "bold")]
139    {
140        let phosphor_bold_font_data = include_bytes!("../assets/fonts/Phosphor-Bold.ttf");
141        fonts.font_data.insert(
142            "phosphor-icons-bold".to_owned(),
143            Arc::new(egui::FontData::from_static(phosphor_bold_font_data)),
144        );
145    }
146
147    #[cfg(feature = "fill")]
148    {
149        let phosphor_fill_font_data = include_bytes!("../assets/fonts/Phosphor-Fill.ttf");
150        fonts.font_data.insert(
151            "phosphor-icons-fill".to_owned(),
152            Arc::new(egui::FontData::from_static(phosphor_fill_font_data)),
153        );
154    }
155
156    #[cfg(feature = "light")]
157    {
158        let phosphor_light_font_data = include_bytes!("../assets/fonts/Phosphor-Light.ttf");
159        fonts.font_data.insert(
160            "phosphor-icons-light".to_owned(),
161            Arc::new(egui::FontData::from_static(phosphor_light_font_data)),
162        );
163    }
164
165    #[cfg(feature = "thin")]
166    {
167        let phosphor_thin_font_data = include_bytes!("../assets/fonts/Phosphor-Thin.ttf");
168        fonts.font_data.insert(
169            "phosphor-icons-thin".to_owned(),
170            Arc::new(egui::FontData::from_static(phosphor_thin_font_data)),
171        );
172    }
173
174    // Create separate font families for each variant
175    // Regular font family
176    fonts.families.insert(
177        egui::FontFamily::Name(PHOSPHOR_REGULAR_NAME.into()),
178        vec!["phosphor-icons".to_owned()],
179    );
180
181    #[cfg(feature = "bold")]
182    fonts.families.insert(
183        egui::FontFamily::Name(PHOSPHOR_BOLD_NAME.into()),
184        vec!["phosphor-icons-bold".to_owned()],
185    );
186
187    #[cfg(feature = "fill")]
188    fonts.families.insert(
189        egui::FontFamily::Name(PHOSPHOR_FILL_NAME.into()),
190        vec!["phosphor-icons-fill".to_owned()],
191    );
192
193    #[cfg(feature = "light")]
194    fonts.families.insert(
195        egui::FontFamily::Name(PHOSPHOR_LIGHT_NAME.into()),
196        vec!["phosphor-icons-light".to_owned()],
197    );
198
199    #[cfg(feature = "thin")]
200    fonts.families.insert(
201        egui::FontFamily::Name(PHOSPHOR_THIN_NAME.into()),
202        vec!["phosphor-icons-thin".to_owned()],
203    );
204}
205
206/// A Phosphor icon that can be rendered with different font styles.
207///
208/// # Example
209/// ```no_run
210/// use egui_phosphor_icons::icons;
211///
212/// // In your egui UI code:
213/// // ui.label(icons::HOUSE.regular());
214/// // ui.label(icons::HOUSE.bold());
215/// // ui.label(icons::HOUSE.fill());
216/// ```
217#[derive(Debug, Clone, Copy)]
218pub struct Icon(pub &'static str);
219
220impl Icon {
221    /// Creates a new Icon from a unicode string.
222    pub const fn new(icon: &'static str) -> Self {
223        Self(icon)
224    }
225
226    /// Returns the raw unicode string for this icon.
227    ///
228    /// Useful for string concatenation when you want to combine icons with text.
229    /// Note that the combined string will use whatever font is applied to it,
230    /// so you'll need to use a font family that includes the Phosphor icons.
231    ///
232    /// # Example
233    /// ```no_run
234    /// use egui_phosphor_icons::icons;
235    ///
236    /// // Combine icon with text
237    /// let text = format!("{} Settings", icons::GEAR.as_str());
238    /// // ui.label(text);
239    /// ```
240    pub const fn as_str(self) -> &'static str {
241        self.0
242    }
243
244    /// Renders the icon using the regular font style.
245    pub fn regular(self) -> egui::RichText {
246        egui::RichText::new(self.0).family(egui::FontFamily::Name(PHOSPHOR_REGULAR_NAME.into()))
247    }
248
249    /// Renders the icon using the bold font style.
250    ///
251    /// Only available with the `bold` feature enabled.
252    #[cfg(feature = "bold")]
253    pub fn bold(self) -> egui::RichText {
254        egui::RichText::new(self.0).family(egui::FontFamily::Name(PHOSPHOR_BOLD_NAME.into()))
255    }
256
257    /// Renders the icon using the fill font style.
258    ///
259    /// Only available with the `fill` feature enabled.
260    #[cfg(feature = "fill")]
261    pub fn fill(self) -> egui::RichText {
262        egui::RichText::new(self.0).family(egui::FontFamily::Name(PHOSPHOR_FILL_NAME.into()))
263    }
264
265    /// Renders the icon using the light font style.
266    ///
267    /// Only available with the `light` feature enabled.
268    #[cfg(feature = "light")]
269    pub fn light(self) -> egui::RichText {
270        egui::RichText::new(self.0).family(egui::FontFamily::Name(PHOSPHOR_LIGHT_NAME.into()))
271    }
272
273    /// Renders the icon using the thin font style.
274    ///
275    /// Only available with the `thin` feature enabled.
276    #[cfg(feature = "thin")]
277    pub fn thin(self) -> egui::RichText {
278        egui::RichText::new(self.0).family(egui::FontFamily::Name(PHOSPHOR_THIN_NAME.into()))
279    }
280
281    /// Looks up an icon by its string name using kebab-case (e.g., "arrow-up-left").
282    ///
283    /// Returns `Some(Icon)` if the name exists, `None` otherwise.
284    /// This is useful for loading icons from serializable formats like JSON or configuration files.
285    ///
286    /// # Example
287    /// ```
288    /// use egui_phosphor_icons::Icon;
289    ///
290    /// let icon = Icon::from_name("arrow-up-left").unwrap();
291    /// // ui.label(icon.regular());
292    ///
293    /// let icon = Icon::from_name("house").unwrap();
294    /// // ui.label(icon.fill());
295    /// ```
296    pub fn from_name(name: &str) -> Option<Icon> {
297        icons::icon_map().get(name).copied()
298    }
299
300    /// Returns an iterator over all available icon names.
301    ///
302    /// Useful for debugging, documentation, or building icon pickers.
303    ///
304    /// # Example
305    /// ```
306    /// use egui_phosphor_icons::Icon;
307    ///
308    /// for name in Icon::names() {
309    ///     println!("{}", name);
310    /// }
311    /// ```
312    pub fn names() -> impl Iterator<Item = &'static str> {
313        icons::icon_map().keys().copied()
314    }
315}
316
317/// Converts an Icon to RichText using the regular font style by default.
318///
319/// This allows Icons to be used directly where RichText is expected.
320///
321/// # Example
322/// ```no_run
323/// use egui_phosphor_icons::icons;
324///
325/// let rich_text: egui::RichText = icons::HOUSE.into();
326/// ```
327impl From<Icon> for egui::RichText {
328    fn from(icon: Icon) -> Self {
329        icon.regular()
330    }
331}
332
333/// Converts an Icon to WidgetText using the regular font style by default.
334///
335/// This allows Icons to be used directly in any egui widget that accepts WidgetText.
336///
337/// # Example
338/// ```no_run
339/// use egui_phosphor_icons::icons;
340/// # fn ui_example(ui: &mut egui::Ui) {
341///
342/// // Icons work directly in labels, buttons, etc.
343/// ui.label(icons::HOUSE);
344/// ui.button(icons::GEAR);
345/// # }
346/// ```
347impl From<Icon> for egui::WidgetText {
348    fn from(icon: Icon) -> Self {
349        icon.regular().into()
350    }
351}