zero_ui/lib/
icon.rs

1use leptos::*;
2
3/// Icon Leptos Component
4///
5/// Icons index: https://carlosted.github.io/icondata/
6///
7/// Documentation: https://github.com/Carlosted/leptos-icons
8#[component]
9pub fn Icon(
10    #[prop(into, optional)] leptos_icons_icon: Option<MaybeSignal<leptos_icons::Icon>>,
11    #[prop(into, optional)] svg_child: Option<MaybeSignal<&'static str>>,
12    #[prop(into, optional)] svg_viewbox: Option<MaybeSignal<String>>,
13    #[prop(into, optional)] id: Option<AttributeValue>,
14    #[prop(into, optional)] class: Option<MaybeSignal<String>>,
15    #[prop(into, optional)] style: Option<AttributeValue>,
16    #[prop(into, optional)] aria_label: Option<AttributeValue>,
17    #[prop(into, optional)] size: Option<MaybeSignal<String>>,
18) -> impl IntoView {
19    let svg = match (leptos_icons_icon, svg_child) {
20        (Some(i), None) => leptos_icons::Icon(leptos_icons::IconProps {
21            icon: i.get().into(),
22            width: size.clone(),
23            height: size.clone(),
24            class: None,
25            style: None,
26        })
27        .into_view(),
28        // If both svg_child and leptos_icons_icon are provided, prioritize svg_child
29        (Some(_), Some(s)) | (None, Some(s)) => view! {
30            <svg
31                xmlns="http://www.w3.org/2000/svg"
32                width=size.clone().unwrap()
33                height=size.clone().unwrap()
34                viewBox=svg_viewbox.clone().unwrap_or("0 0 24 24".into())
35                fill="none"
36                stroke="currentColor"
37                stroke-width="2"
38                stroke-linecap="round"
39                stroke-linejoin="round"
40                inner_html=s.get()
41            ></svg>
42        }
43        .into_view(),
44        (None, None) => view! {
45            <svg
46                xmlns="http://www.w3.org/2000/svg"
47                width=size.clone().unwrap()
48                height=size.clone().unwrap()
49                viewBox="0 0 24 24"
50                fill="none"
51                stroke="currentColor"
52                stroke-width="2"
53                stroke-linecap="round"
54                stroke-linejoin="round"
55            >
56                <circle cx="12" cy="12" r="10"></circle>
57                <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path>
58                <line x1="12" y1="17" x2="12.01" y2="17"></line>
59            </svg>
60        }
61        .into_view(),
62    };
63
64    let default_class = "h-9 w-9 flex shrink-0 justify-center items-center hover:brightness-150";
65
66    let parsed_class = match class {
67        Some(signal) => signal.get(),
68        None => default_class.into(),
69    };
70
71    view! {
72        <div id=id class=parsed_class style=style aria_label=aria_label>
73            {svg}
74        </div>
75    }
76}
77