icon.rs
⎇
Raw
1//! The `Icon` component: renders a glyph from the central [`crate::icons`]
2//! registry (Material Symbols via Iconify) as inline SVG.
3
4use leptos::prelude::*;
5
6use crate::icons::IconName;
7
8/// Folder-shaped glyphs get the accent color; everything else stays muted.
9fn icon_class(name: IconName) -> &'static str {
10 if name.is_folder() {
11 "ic-folder"
12 } else {
13 "ic-muted"
14 }
15}
16
17#[component]
18pub fn Icon(name: IconName, #[prop(optional)] class: Option<String>) -> impl IntoView {
19 let node = NodeRef::<leptos::svg::Svg>::new();
20 let body = name.body().to_string();
21 node.on_load(move |el: web_sys::SvgElement| {
22 // The registry bodies are raw SVG markup (`<path …/>`), so they are
23 // injected as-is. The strings are static and fetched from the
24 // Iconify API — never user input.
25 el.set_inner_html(&body);
26 });
27 let mut cls = String::from("icon ");
28 cls.push_str(icon_class(name));
29 if let Some(extra) = class {
30 cls.push(' ');
31 cls.push_str(&extra);
32 }
33 view! {
34 <svg
35 node_ref=node
36 class=cls
37 viewBox="0 0 24 24"
38 fill="currentColor"
39 aria-hidden="true"
40 />
41 }
42}
43