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}