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

Convenience APIs for adding icons/images to list items #2688

Open
rolfsmeds opened this issue Feb 16, 2022 · 4 comments
Open

Convenience APIs for adding icons/images to list items #2688

rolfsmeds opened this issue Feb 16, 2022 · 4 comments
Labels
enhancement New feature or request

Comments

@rolfsmeds
Copy link
Contributor

Describe your motivation

Rendering icons or images as part of items in lists is an extremely common use case:

  • Menus often have icons next to their item's labels, providing a visual representation of the option or action.
  • Dropdown fields often have small images (icons, avatars, thumbnails...) as part of the items in their dropdown lists for the same reason.

Yet implementing these with Vaadin components like ComboBox, Select, MenuBar and ContextMenu requires a significant amount of boilerplate code for creating the layout containing the image and the label, and applying a classname or a bit of inline css to it. What could be a single line of code tends to be closer to at least five, and it is far from trivial to figure out how to do it.

Describe the solution you'd like

Simple, single-liner APIs for rendering images, icons, or why not any arbitrary component as a "prefix" to items in menus and lists.

Vaadin 8 had the ItemIconGenerator API, so that would seem like a pretty good option for ComboBox and Select (although I think ItemImageGenerator, or even ItemPrefixGenerator, would be preferable, as it's not always icons specifically).

The add-methods of MenuBar and ContextMenu could simply be overloaded with a second parameter for the prefix component:

menubar.addItem(VaadinIcon.ABACUS.create(), "Calculate stuff");

In terms of implementation, it would seem logical to add a slot for the prefix element in vaadin-item, which all of the above components use for their items, and ensuring that it, and the label next to it, are rendered nicely.

Additional context

This would also make it easier to migrate applications from Vaadin 7 and 8, in which corresponding APIs are used a lot.

@web-padawan web-padawan added the enhancement New feature or request label Feb 17, 2022
@yuriy-fix
Copy link
Contributor

Possibly related: vaadin/web-components#459

@sosa-vaadin
Copy link
Contributor

The example provided in the menu-bar docs is a good example of how to solve this using a factory method.

Regarding this:

The add-methods of MenuBar and ContextMenu could simply be overloaded with a second parameter for the prefix component:
menubar.addItem(VaadinIcon.ABACUS.create(), "Calculate stuff");

I think this could be implemented with a default method in the HasMenuItems interface. This solution overloads the other methods in the interface and provides developers with a one-line solution to add items with an icon and a label or just an icon.

default MenuItem addItem(Icon icon, String text, ComponentEventListener<ClickEvent<MenuItem>> clickListener) {
    MenuItem item = addItem(icon, clickListener);
    if (text != null) {
        item.add(new Text(text));
    }
    return item;
}

This, however, doesn't provide a solution for ComboBox or Select since they don't implement the HasMenuItems interface. It should also be noted, that additional styling might be needed to have the items render nicely in sub-menus

@mvysny
Copy link
Member

mvysny commented Nov 15, 2023

The solution above doesn't look quite good when items both with and without icon are mixed:

@Route("")
public class MainView extends VerticalLayout {

    private static MenuItem addItem(HasMenuItems self, Icon icon, String text) {
        MenuItem item = self.addItem(icon, event -> {});
        if (text != null) {
            item.add(new Text(text));
        }
        return item;
    }

    public MainView() {
        final MenuBar menuBar = new MenuBar();
        add(menuBar);
        final MenuItem fooItem = menuBar.addItem("Foo");
        addItem(fooItem.getSubMenu(), VaadinIcon.ABACUS.create(), "Abacus");
        fooItem.getSubMenu().addItem("Text", e -> {});
    }
}

Screenshot from 2023-11-15 10-12-33

The icon solution should look similar to checkable items solution:

image

@jouni
Copy link
Member

jouni commented Nov 15, 2023

The solution above doesn't look quite good when items both with and without icon are mixed

I think that case should be fixed with an empty icon instead of forcing the padding on all items.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants