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

Can I add an icon to a button #408

Open
1 task done
cverluiseQB opened this issue Apr 5, 2024 · 2 comments
Open
1 task done

Can I add an icon to a button #408

cverluiseQB opened this issue Apr 5, 2024 · 2 comments
Assignees
Labels
Community Issue/PR opened by the open-source community Issue: Feature Request 🤓 Issue/PR contains a feature request or is based on a feature request

Comments

@cverluiseQB
Copy link

Which package?

vizro

What's the problem this feature will solve?

As a developer, I would like to easily communicate the purpose of a button using standard icons.

Describe the solution you'd like

A simple option would be to add an icon field to the vm.Button here a valid material icon name could be passed (similar to what is done for nav) so that the icon is natively rendered at the left of the text of the button

Alternative Solutions

Document how this can be done with custom component (e.g. pointing at the code of the export data button).

Additional context

Nothing to add

Code of Conduct

@cverluiseQB cverluiseQB added Issue: Feature Request 🤓 Issue/PR contains a feature request or is based on a feature request Status: Needs triage 🔍 Issue/PR needs triaging labels Apr 5, 2024
@huong-li-nguyen huong-li-nguyen self-assigned this Apr 8, 2024
@huong-li-nguyen huong-li-nguyen removed the Status: Needs triage 🔍 Issue/PR needs triaging label Apr 8, 2024
@huong-li-nguyen
Copy link
Contributor

Hey @cverluiseQB,

yes, there is! Generally, whenever you find yourself in a situation where you want to extend the functionality of an existing component, creating custom components is the answer 👍

I want to emphasize two additional changes, though:

  • Because we're using the span HTML element with the provided className material-symbols-outlined , you can give a string to the icon argument, which will pull the relevant icon from the Google Material Icon Library. So no need to have any physical files in your assets folder! 🚀
  • Some CSS changes are required to make it look good, though, so add this to a CSS file using the assets folder.
.text-with-icon {
  display: flex;
  gap: 4px;
}

.text-with-icon .material-symbols-outlined {
  color: unset;
}

Example

from typing import Literal

import vizro.models as vm
from dash import HTML
from vizro import Vizro


class CustomButton(vm.Button):
    """Custom Button that allows for an icon."""

    type: Literal["custom_button"] = "custom_button"
    icon: str = "Download"

    def build(self):
        button_build = super().build()
        button_build[self.id].children = html.Div(
            [html.Span(self.icon, className="material-symbols-outlined"), self.text], className="text-with-icon"
        )
        return button_build


vm.Page.add_type("components", CustomButton)

page = vm.Page(title="Custom Button", components=[CustomButton(text="Export Data", icon="Download")])
dashboard = vm.Dashboard(pages=[page])


Vizro().build(dashboard).run()

Screenshot 2024-04-05 at 16 36 35

@huong-li-nguyen huong-li-nguyen added the Community Issue/PR opened by the open-source community label Apr 8, 2024
@antonymilne
Copy link
Contributor

This is a great question @cverluiseQB, thanks for posting it here so we have it on the open source repo 👍 And great answer @huong-li-nguyen 💯

A couple of notes for future reference: this is something that dmc natively enables through dash-iconify and e.g. dmc.Button with leftIcon and rightIcon arguments. I don't think we want to have that much flexibility on all our components but a new icon field that handles an icon using Google material library just like @huong-li-nguyen suggests sounds like the right solution here if it is something that we want to add.

Another thing I've wondered before is whether we should just encourage users who want to do such things to relax the field types. e.g. vm.Button has text: str but if you relaxed that to Any then you could directly do this:

class CustomButton(vm.Button):
    """Custom Button that allows for an icon."""

    type: Literal["custom_button"] = "custom_button"
    text: Any

CustomButton(text=html.Div([html.Span("Download", className="material-symbols-outlined"), "Export Data"], className="text-with-icon"))

(completely untested, might not work, but hopefully you get the general idea)

The advantage of this is that it has infinite flexibility since you could put whatever you like in text then - i.e. put the icon wherever you like inside the label, put in any sort of HTML, etc. For example, previously I wanted to put text formatted as code into a page title using html.Pre and it was awkward because of our title: str limitation.

The disadvantage is that the model becomes much less prescriptive. On the Vizro side it would be much cleaner to have a new icon field than just allow arbitrary content in text. So I don't want us to do this in Vizro itself, but depending on how much flexibility the user requires it might sometimes be a good solution for writing a custom component.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Community Issue/PR opened by the open-source community Issue: Feature Request 🤓 Issue/PR contains a feature request or is based on a feature request
Projects
None yet
Development

No branches or pull requests

3 participants