openui / open-ui

Maintain an open standard for UI and promote its adherence and adoption.
https://open-ui.org
Other
3.58k stars 191 forks source link

[MISC] How should the icons/glyphs be implemented? #28

Closed gregwhitworth closed 4 years ago

gregwhitworth commented 4 years ago

In issues #26 and #27 we've begun to discuss icons/glyphs that are commonly included in controls such as <input type="date">, <input type="password">, <input type="checkbox">, "`, etc. There are many ways in which we can implement this, all have pros and cons:

  1. Background image: We can have it be a background image and standardize this so that authors no to override the background image to their own custom icon/glyph.

  2. Inline SVG with CSS propagation: Implement it using SVG which will allow web developers to adjust the styles of the SVG but not adjust the glyph itself since it will be in-content

  3. All icons should be both in a ::part and a ::slot to allow for either of the above of the part but also allow the web developer to completely replace the content with whatever they want.

My instinct is to do 3 + 1 or 2 but there are tradeoffs that need to be made. There may also be things that 3 may cause complications but I can build out a web component that's similar.

Let me know your thoughts.

gregwhitworth commented 4 years ago

An additional aspect that I thought about is that pseudo's don't have event listeners attached to them. It would be valuable to understand from the various design systems if there have been desires to adjust the behavior based on an event that isn't being listened and bubbled by the component. An example we've been discussing recently is password reveals, there are scenarios where some implementations only reveal the text of the password while the button is "active" and then others it toggles on click. I'd be interested to hear thoughts on this as we begin to think of extensibility.

levithomason commented 4 years ago

In frameworks, icons are usually an <i> or <span> element. Folks used to use images, then font icons took off, and now SVGs seem the most flexible and first choice, at least in my experience. This is because SVGs offer the most flexibility. They render sharp on all screen densities, allow for animations, and multiple colors.

Many component libraries lock themselves into a particular icon set. When we were planning out Fluent UI our main goal was to avoid lock in. So, we allow the user to define any type of icon they like. So, I'm partial to your #3, where the icon is a slot and the consumer can put their icon in if they like. Anything else will alienate the rest of the icon world. It also won't scale over time when the next icon fad hits the web.

Would love to hear your feedback and more input on this. @chrisdholt? @dzearing?

jouni commented 4 years ago

where the icon is a slot and the consumer can put their icon in if they like

I think any solution that requires per-instance customizations to update icons is quite limited. It should be possible to override the icon set which is used by an app/components on the ”theme level”, not only on an instance level. I don’t think a slot is enough for that.

gregwhitworth commented 4 years ago

@jouni I think a slot is sufficient for a single adjustment. Can you expound on the theme adjustment statement? My instinct is that this would be provided by a theme to the component(s) via CSS/HTML/JS which would be providing new icons for all components that use an icon which would be leveraging the slotting extensibility. These would be layered on top of the defaults but allow for replacement by other themes. Is this not sufficient or am I missing something?

chrisdholt commented 4 years ago

I agree with @levithomason here and think a slot approach definitely provides the broadest opportunity to support variation and custom scenarios.

@gregwhitworth - from a platform standpoint, while I don't think we want to get too fancy here, I had an interesting idea of having the default platform icon/glyph render as a background image and if a slot existed it wouldn't render. I don't want things to get convoluted, but it would be interesting to have a simple CSS solution (background image or pseudo) while providing a slot API that folks could use for SVG or when custom events are needed for that portion of the menu...just a (potentially crazy) thought.

gregwhitworth commented 4 years ago

@chrisdholt My instinct is that we'll have an inline SVG within the slot and allow a way for this to have style adjustments. This is important because a site may be fine with the graphic itself but may only want to change the fill or stroke colors. Then if any design system places their own content (svg or not) it will over-write the content within it as any other slot does.

chrisdholt commented 4 years ago

Thanks for the quick response @gregwhitworth. I think this would be our ideal. One potential gap to think through - in the case that I do not want to render the default glyph or my own, do I need to pass a blank element to the slot?

gregwhitworth commented 4 years ago

@chrisdholt nope - that's why it gets a part name as well so that you can set display: none; on it :)

jouni commented 4 years ago

@gregwhitworth

I think a slot is sufficient for a single adjustment.

Yes, agreed. Though, I would rather keep styling-related configuration in CSS than in HTML or JS.

Can you expound on the theme adjustment statement?

As an example, I have an app with multiple instances of a 3rd party date picker component. The date picker comes with a built-in icon which I want to change. It would be bad if I had to do that per-instance, which I think we agree on.

I haven’t given enough thought to how I would prefer to get it done, but my personal preference always goes to CSS when talking about styling/theming.

A custom property for the icon would perhaps be my first choice, something like --fancy-date-picker-calendar-icon, which could accept an icon name, e.g. --fancy-date-picker-calendar-icon: my-calendar-icon;. That name would then be resolved by the component to an SVG path somehow (some sort of icon dictionary) and render it inline (like you said, to be able to style it).

A slot could still be utilized for rendering the SVG. So I’m looking for some more convenience on top of the slot, not trying to dismiss the slot idea altogether.

gregwhitworth commented 4 years ago

Closing this out - in most scenarios we're going to be providing the slot now for content (eg: 3). This provides the greatest extensibility with part information for styling assuming interop.