Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use icons in for loops? #49

Open
nxy7 opened this issue Jun 29, 2024 · 8 comments
Open

How to use icons in for loops? #49

nxy7 opened this issue Jun 29, 2024 · 8 comments
Assignees
Labels
question Further information is requested

Comments

@nxy7
Copy link

nxy7 commented Jun 29, 2024

Here's what I'm trying to do

image

I've tried using tuples, boxing the Icons, but nothing seems to work. Actually IDK if that's possible but maybe it would be nice to provide IconShape implementation for anything that can be dereferenced into IconShape (but that's separate issue)?

Is it possible to create vector of icons and display it?

@marc2332 marc2332 self-assigned this Jun 29, 2024
@marc2332
Copy link
Member

Hey 👋🏻

Can you share the full error and the definition of NavbarLink?

@marc2332
Copy link
Member

Also of GenericIcon

@nxy7
Copy link
Author

nxy7 commented Jun 29, 2024

I've tried multiple things so definition of NavbarLink is not very relevant here. Here's what I've tried:

pub struct NavbarLink {
    pub name: String,
    pub route: DashboardRouter,
    pub icon: &'static dyn IconShape,
}
and
pub struct NavbarLink {
    pub name: String,
    pub route: DashboardRouter,
    pub icon: Box<dyn IconShape>,
}

Boxing shape results in:

the trait bound `std::boxed::Box<dioxus_free_icons::icons::ld_icons::LdAArrowUp>: dioxus_free_icons::IconShape` is not satisfied
the following other types implement trait `dioxus_free_icons::IconShape`:
  dioxus_free_icons::icons::ld_icons::LdAArrowDown
  dioxus_free_icons::icons::ld_icons::LdAArrowUp
  dioxus_free_icons::icons::ld_icons::LdALargeSmall
  dioxus_free_icons::icons::ld_icons::LdAccessibility
  dioxus_free_icons::icons::ld_icons::LdActivity
  dioxus_free_icons::icons::ld_icons::LdAirVent
  dioxus_free_icons::icons::ld_icons::LdAirplay
  dioxus_free_icons::icons::ld_icons::LdAlarmClock
and 1448 others

I've tried to make my own GenericIcon to provide implementation for Box

#[derive(Clone)]
pub struct GenericIcon(Box<dyn IconShape>);
impl IconShape for GenericIcon {
    fn view_box(&self) -> &str {
        self.0.view_box()
    }

    fn xmlns(&self) -> &str {
        self.0.xmlns()
    }

    fn child_elements(&self) -> Element {
        self.0.child_elements()
    }
}

but that doesn't work since IconShape doesn't imply Clone and I think Icon needs to be Clone to be used in rsx! (?)

the trait bound `dyn dioxus_free_icons::IconShape: std::clone::Clone` is not satisfied
required for `std::boxed::Box<dyn dioxus_free_icons::IconShape>` to implement `std::clone::Clone`

Basically I'd like to know any way to have vector of Icons in any generic form that can be used atm (or if that's not doable rn).

@marc2332
Copy link
Member

Can you paste your code?

@nxy7
Copy link
Author

nxy7 commented Jun 29, 2024

I guess that would be the minimal example (I got rid of NavbarItem and GenericIcon as they don't really matter here)

use dioxus_free_icons::{Icon, IconShape};

use crate::{prelude::*, router::DashboardRouter};

#[component]
pub fn DashboardLayout() -> Element {
    rsx! {
        DashboardNavbar {}
        Outlet::<DashboardRouter> {}
    }
}

#[component]
fn DashboardNavbar() -> Element {
    use dioxus_free_icons::icons::ld_icons::*;
    let navbar_items: Vec<(&str, DashboardRouter, Box<dyn IconShape>)> = vec![
        (
            "One Link",
            DashboardRouter::Dashboard {},
            Box::new(LdAArrowUp),
        ),
        (
            "Another Link",
            DashboardRouter::Dashboard {},
            Box::new(LdAArrowDown),
        ),
    ];

    rsx! {
        nav {
            ul {
                for link in navbar_items {
                    li {
                        Icon { width: 30, height: 30, fill: "black", icon: link.2 }
                        Link { to: link.1, {link.0} }
                    }
                }
            }
        }
    }
}

which gives me the following error

the trait bound `std::boxed::Box<dyn dioxus_free_icons::IconShape>: dioxus_free_icons::IconShape` is not satisfied
the following other types implement trait `dioxus_free_icons::IconShape`:
  dioxus_free_icons::icons::ld_icons::LdAArrowDown
  dioxus_free_icons::icons::ld_icons::LdAArrowUp
  dioxus_free_icons::icons::ld_icons::LdALargeSmall
  dioxus_free_icons::icons::ld_icons::LdAccessibility
  dioxus_free_icons::icons::ld_icons::LdActivity
  dioxus_free_icons::icons::ld_icons::LdAirVent
  dioxus_free_icons::icons::ld_icons::LdAirplay
  dioxus_free_icons::icons::ld_icons::LdAlarmClock
and 1448 others

@marc2332
Copy link
Member

Could you try something like this?

use dioxus_free_icons::{Icon, IconShape};

use crate::{prelude::*, router::DashboardRouter};

#[component]
pub fn DashboardLayout() -> Element {
    rsx! {
        DashboardNavbar {}
        Outlet::<DashboardRouter> {}
    }
}

#[component]
fn DashboardNavbar() -> Element {
    use dioxus_free_icons::icons::ld_icons::*;
    let navbar_items: Vec<(&str, DashboardRouter, props)> = vec![
        (
            "One Link",
            DashboardRouter::Dashboard {},
            IconProps { icon: LdAArrowUp },
        ),
        (
            "Another Link",
            DashboardRouter::Dashboard {},
            IconProps { icon: LdAArrowDown },
        ),
    ];

    rsx! {
        nav {
            ul {
                for (title, route, icon_props) in navbar_items {
                    li {
                        Icon { width: 30, height: 30, fill: "black", ..icon_props }
                        Link { to: route, "{title}" }
                    }
                }
            }
        }
    }
}

@nxy7
Copy link
Author

nxy7 commented Jun 30, 2024

I don't think I can do that as IconProps is generic over IconShape, so each new IconProp would be another type, right? Because of this I can't get this to work. F.e. something like

    let prop = IconProps {
        icon: LdAArrowDown,
        height: 20,
        width: 20,
        fill: "".into(),
        class: "".into(),
        title: "".to_owned().into(),
    };
    let another_prop = IconProps {
        icon: LdALargeSmall,
        height: 20,
        width: 20,
        fill: "".into(),
        class: "".into(),
        title: "".to_owned().into(),
    };
    let vec = vec![prop, another_prop];

will result in

mismatched types
expected struct `dioxus_free_icons::IconProps<dioxus_free_icons::icons::ld_icons::LdAArrowDown>`
   found struct `dioxus_free_icons::IconProps<dioxus_free_icons::icons::ld_icons::LdALargeSmall>`

I think that there should be some IconShape implementation for smart pointers, maybe something like

impl<T> IconShape for Box<T>
where
    T: IconShape,
{
    fn view_box(&self) -> &str {
        self.view_box()
    }

    fn xmlns(&self) -> &str {
        self.xmlns()
    }

    fn child_elements(&self) -> Element {
        self.child_elements()
    }
}

would be enough so we could have vector of Boxed icons?

@marc2332
Copy link
Member

impl<T> 
where
    T: IconShape,
{
    fn view_box(&self) -> &str {
        self.view_box()
    }

    fn xmlns(&self) -> &str {
        self.xmlns()
    }

    fn child_elements(&self) -> Element {
        self.child_elements()
    }
}

Yeah, seems like implementing IconShape for Box<T> is the way to go

@marc2332 marc2332 added the question Further information is requested label Aug 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants