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

feat: Icon picker component (WIP) #3487

Open
wants to merge 9 commits into
base: next
Choose a base branch
from

Conversation

neatbyte-vnobis
Copy link
Collaborator

@neatbyte-vnobis neatbyte-vnobis commented Aug 21, 2023

Changes

Implements issue "Icon picker component".

Implementation steps

Most of the implementation is described here.

For custom icon support IconPickerConfig was added under packages/app-admin/src/components/IconPicker/config/index.tsx.
For the most part it is similar to what we've done with audit logs here.
It allows to add custom icons/emojis inside DefaultIcons. Also there is an example of how it can be used.

UI

Color Picker UI is currently only available on /page-builder/block-categories page for test purposes.
image

How Has This Been Tested?

Manual

Documentation

None

@neatbyte-vnobis
Copy link
Collaborator Author

@Pavel910 @SvenAlHamad I have a couple questions about Icon Picker:

  1. Emojis need to be displayed by category?
    There is a People category on design, but nothing about it in doc. I'am asking, because it may not be that easy to implement with react-virtualized Grid component.

  2. How will we store our custom icons?
    I see two possible solutions:
    a) Create a separate api for custom icons.
    b) Use the existing File Manager api. We can add flag (e.g. isIcon) under file meta property, when a user adds an icon to Icon Picker. And remove it when the user deletes it from Icon Picker.

@neatbyte-vnobis
Copy link
Collaborator Author

@Pavel910 @SvenAlHamad
Please take a look at the questions above.

Comment on lines 140 to 173
const renderCell = useCallback(() => {
return function renderCell({
columnIndex,
key,
rowIndex,
style
}: GridCellProps): React.ReactNode {
const item = filteredIcons[rowIndex * COLUMN_COUNT + columnIndex];
if (!item) {
return null;
}

return (
<Cell
key={key}
style={style}
onClick={() => {
onChange({
type: item.type,
name: item.name,
...(item.type === "emoji" ? { skinTone: item.skinTone } : {}),
...(item.type === "icon" ? { color } : {}),
...(item.width ? { width: item.width } : {}),
value: item.value
});
}}
color={color}
isActive={item.name === value.name}
>
<IconRenderer icon={item} size={32} />
</Cell>
);
};
}, [filteredIcons, color]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is overcomplicated; Why return a new function? Further down in JSX, you just call renderCell() when passing it to props, so you can essentially just do this:

const renderCell = useCallback(({ columnIndex, key, rowIndex }) => { .... }, [filteredIcons, color]);

And then you pass renderCell as a cellRenderer prop without invoking it.

Comment on lines 226 to 227
const emojis = icons.filter(icon => icon.type === "emoji");
const defaultIcons = icons.filter(icon => icon.type === "icon");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something you want to memoize with useMemo.

};

export const IconPackProvider = ({ provider }: IconPackProviderProps) => {
const icons = provider();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this work with async providers? Think code splitting... Would be nice to allow icons to be lazy loaded, or even loaded from an API. That way they'll only load when IconPicker is actually being used in the UI.

@SvenAlHamad
Copy link
Contributor

I was testing the icon component implementation and have a few UX related points that require a bit of polish:

  • improve the search: if I search for "glass" or "magnifying glass" I don't get the icon of a magnifying glass; but if I search for "magnifying-glass" then I get it. We should improve the search so that in both these cases I get the expected result.
  • empty state: when we have an empty icon field, can add the magnify glass as the default placeholder, just lower the opacity on the icon in that case so that we hint to the user this is an empty state for the icon field
  • when I select and icon, automatically close the window; currently I need to click manually outside the window to close it
  • when I have a search query in one tab (say I wrote "boat" in the input field in the icons tab) and if I switch to the emoji tab, keep the same value in the input

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

Successfully merging this pull request may close these issues.

None yet

3 participants