mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
4k stars 1.24k forks source link

Add an Icon Picker component #13206

Closed TheOneTheOnlyJJ closed 1 month ago

TheOneTheOnlyJJ commented 3 months ago

Summary

I've recently come across the need to allow users to select arbitrary icons for display in chips. For stylistic consistency with the rest of the UI, I only want to allow them to select icons from the Material Icons selection, and specifically only the outlined style. Looking for a way to do this, I've realised that the icon browser from the Material Icons page on the official website is just the tool I need. Given that it's already there, I figured it may be possible to expose it as a library component.

The Icon Picker could take as arguments the icons, their display names, and their style/category tag(s). The radio button style/category selector menu on the left could be generated internally based on the icon categories provided. Multiple selection could be supported as well.

To use it with the current Material Icons, like on the official page, the @mui/icons-material package (or the Icon Picker's component module) could export a new utility function to generate the icon lists required as inputs for the Icon Picker. This function could take as arguments the style of the icons to be returned (one or more of filled, outlined, rounded, two tone, sharp). A way to obtain the desired display name text for each icon should also be provided. Maybe by having as a 2nd function argument a transformer callback that gets mapped to every icon name. This way, we could turn their names from camel case into natural human format, or any other format we desire.

Examples

The official website icon browser (as of the opening of this issue): image

Motivation

There is no easy way to prompt a user to pick an icon (or more), while there already is such a component on the official Material UI website, on the Material Icons page.

Search keywords: icon picker component material icons

LukasTy commented 3 months ago

Thank you for an interesting suggestion. πŸ™ The idea makes total sense, I'm just not sure which package/repository it should belong to. I'm leaning towards this being a @mui/lab export; thus, this is more of a mui/material-ui repository issue. WDYT @joserodolfofreitas @michelengelen?

TheOneTheOnlyJJ commented 3 months ago

I'm just not sure which package/repository it should belong to. I'm leaning towards this being a @mui/lab export; thus, this is more of a mui/material-ui repository issue.

I opened this issue here based on the premise that this is the place for complex components having specific functionalities above and beyond the basic building blocks offered by mui/material-ui.

michelengelen commented 3 months ago

@LukasTy this feels like it should be in the labs repo for exploration. I can imagine there might be more functionalities we could be building this with (custom emoji picker, kaomoji pickers, fonts, etc.) Interested on your opinion though @joserodolfofreitas

TheOneTheOnlyJJ commented 3 months ago

@LukasTy this feels like it should be in the labs repo for exploration. I can imagine there might be more functionalities we could be building this with (custom emoji picker, kaomoji pickers, fonts, etc.) Interested on your opinion though @joserodolfofreitas

Upon further consideration, I believe it could be implemented as a general-purpose content picker, ingesting any kind of content through its arguments and offering callbacks that get applied to said content. For example, how to display the content, how to format the display name, how to handle content categories, what callback to run when selecting content, etc. It truly has the potential to handle a lot of use cases, but its complexity would be a lot greater than what I was initially imagining.

LukasTy commented 3 months ago

@TheOneTheOnlyJJ it feels like we are leaning towards a customizable Autocomplete approach or something that downshift provides. πŸ€” What features do you think the Autocomplete is missing to cover what you are imagining?

TheOneTheOnlyJJ commented 3 months ago

@TheOneTheOnlyJJ it feels like we are leaning towards a customizable Autocomplete approach or something that downshift provides. πŸ€” What features do you think the Autocomplete is missing to cover what you are imagining?

The main attraction of this picker over the current Autocomplete is the UI, as showing over 2100+ icons in a vertical dropdown menu is not ideal for UX. I feel like the Autocomplete is the best choice for when users have to select text, but it does not provide that good of an experience for visual content/media. For my use case, when the user wants to select an icon, the emphasis should be on the icons themselves, not as much on their names. I can even imagine turning this into a media gallery browser if we could support Cards as selectable content. Being able to select the content size and number of columns would make it very flexible for different size emphasis of the content.

I forgot to mention this initially, but the icon browser from the official website recommends icons based on synonyms as well, which I do not see how to achieve with an Autocomplete component. The one from Google's Material Icons page does the same, and is similar to the one from Material UI. Supporting this would greatly increase UX, especially given how icons can be described by many words different to their names.

Also of note is the way users can filter the content based on categories. In the one from the MUI website, there are radio buttons on the left to do this. In the Autocomplete, the groups are merely an indication as to what category of content you are currently browsing through while searching for your desired option, and there is no out-of-the-box way to exclude categories entirely from the selection options. Going even further into this, if we refer to the categories as content tags, we could even support nested tags through having a Tree View with Checkbox selection enabled instead of the current Radio Buttons.

This kind of component would be very useful for a wide variety of use cases. Just while writing this reply I've come up with the following ideas for potential use cases:

If Cards are supported, the possibilities are truly endless, as any kind of compact displayable content could be made easily selectable by this component. The DX would improve a lot and the stylistic consistency of apps built with MUI would benefit, as this component could see extensive use. Dashboards could make very good use of this. I believe there's enough feature area to cover that this could have features included in the paid plans as well.

TheOneTheOnlyJJ commented 3 months ago

Also, for my specific use case of selecting icons, even if I would use an Autocomplete component, I still have no way to import all the icons of a specific style at once. The utility function that returns all the icons from the icons package with optional specific styles only is still required to make this possible to implement. It is not feasible to write out thousands of imports by hand :)

LukasTy commented 3 months ago

Thank you for all the detailed input! πŸ™ I'm putting this issue into the eXplore team grooming list. πŸ˜‰

TheOneTheOnlyJJ commented 3 months ago

Thank you for all the detailed input! πŸ™ I'm putting this issue into the eXplore team grooming list. πŸ˜‰

This might be off-topic, but is this list public so we can see what the team is cooking a little earlier?

LukasTy commented 3 months ago

Sorry, no, only the Public Roadmap is available for everyone. πŸ˜‰

TheOneTheOnlyJJ commented 2 months ago

I would like to add an explicit example of how the utility function from the icons package I was talking about could look like:

import { getIcons } from '@mui/icons-material';
import SvgIcon from '@mui/material/SvgIcon';

// Get all icons in all styles
let allIcons: Array<SvgIcon> = getIcons();

// Get all outlined icons
let allOutlinedIcons: Array<SvgIcon> = getIcons({ styles: [ 'outlined' ] });

// Get only filled and outlined icons
let filledAndOutlinedIcons: Array<SvgIcon> = getIcons({ styles: [ 'filled', 'outlined' ] });

// Get only filled icons with the "home" tag
// Should only return these icons: https://mui.com/material-ui/material-icons/?query=home
let filledHomeIcons: Array<SvgIcon> = getIcons({ styles: [ 'filled' ], tags: { anyOf: [ 'home' ] } });

// Get all icons with the "home" tag, in all styles
let allHomeIcons: Array<SvgIcon> = getIcons({ tags: { anyOf: [ 'home' ] } });

// Get all icons that have either the "home" or the "building" tags, in all styles
let allHomeOrBuildingIcons: Array<SvgIcon> = getIcons({ tags: { anyOf: [ 'home', 'building' ] } });

// Get all icons that have both the "home" and "building" tags, in the sharp style only
let allSharpHomeAndBuildingIcons: Array<SvgIcon> = getIcons({ styles: [ 'sharp' ], tags: { allOf: [ 'home', 'building' ] } });

// Do not support allOf and anyOf at the same time
let willThrowException = getIcons({ tags: { anyOf: [ 'home' ], allOf: [ 'building' ] } });

The styles argument is optional and, if missing, every style will be included in the output. It is a string array that can have any of the following options filled, outlined, rounded, two tone and sharp. These could additionally also be exported as enums to be used in code conveniently.

The tags argument is also optional, and its filtering will apply together with the style filter. It is an object that must have either the anyOf or the allOf keys that map to string arrays. They should not be both supported at the same time, resulting in an exception being thrown. Using the argument with anyOf option will return all the icons that have at least one of the tags in the list. Using it with the allOf option will return only the icons that have all the tags from the given tag list.

With this kind of API, the Icon Picker component can pass its state as arguments to the getIcons function and fulfil my requirement. When the user would change the style option(s) or change the search word, the state would update and call the function again, and the Icon Picker would rerender to only display the new icons returned by getIcons. Having both the anyOf and the allOf tag selectors will enable this component to potentially use Chip-based sorting as well as the already discussed Radio Button/Tree View variants.

Additionally, a function that allows getting all tags for a specific icon (maybe call it getIconTags) should also be available for flexibility (to show the user the keywords/tags a specific icon can be found by), but this would require an internal ID for every icon to be passed as an argument to that function. I am not that accustomed to the internals of the icons package, so I do not know how difficult such an addition would be.

If this icons-related reply is out of topic here, feel free to move (or copy) this issue to the corresponding repository (material-ui).

oliviertassinari commented 1 month ago

Closing as won't fix. The looks like a niche use case that has little intrinsic complexity to solve, so not relevant for MUI X. It looks like an AI model could easily solve this.

github-actions[bot] commented 1 month ago

:warning: This issue has been closed. If you have a similar problem but not exactly the same, please open a new issue. Now, if you have additional information related to this issue or things that could help future readers, feel free to leave a comment.

@TheOneTheOnlyJJ: How did we do? Your experience with our support team matters to us. If you have a moment, please share your thoughts in this short Support Satisfaction survey.

TheOneTheOnlyJJ commented 4 weeks ago

Closing as won't fix. The looks like a niche use case that has little intrinsic complexity to solve, so not relevant for MUI X. It looks like an AI model could easily solve this.

I agree with you. This issue was opened to address the pain point of importing and searching for the icons more than the icon picker itself. Even with this rightfully closed, I still believe the icons package could receive an overhaul consisting of something similar to what was suggested in mui/material-ui#42450 and in mui/material-ui#42704.