mui / material-ui

MaterialĀ UI: Ready-to-use foundational React components, free forever. It includes Material UI, which implements Google's Material Design.
https://mui.com/material-ui/
MIT License
91.86k stars 31.57k forks source link

Support Material Symbols (Icon v2) #32846

Open oliviertassinari opened 1 year ago

oliviertassinari commented 1 year ago

Duplicates

Latest version

Summary šŸ’”

Google has recently introduced a new major iteration on their icon system: Material Symbols: https://material.io/blog/introducing-symbols. This is an awesome new iteration on their icon system, and more importantly, they have made it the default! Proof https://fonts.google.com/icons. This new iteration seems much better.

Screenshot 2022-05-21 at 17 00 35

For SVGs, we might be able to implement the weight with the stroke-width attribute, see: https://feathericons.com/ but we might have to build these SVGs ourselves: https://github.com/google/material-design-icons/issues/1360.

Examples šŸŒˆ

Motivation šŸ”¦

We will need to update our icons to reflect this change, both for font and SVG icons. It's an important step forward in terms of icon

gautamV19 commented 1 year ago

Is there anything left in this issue?

oliviertassinari commented 1 year ago

@gautamV19 Everything is left to be done, in case it's something you would like to have a look at.

ErreMalote commented 1 year ago

@oliviertassinari

here it is a react based material symbols maybe using the same patter to create this iteration of Material Symbols.

https://github.com/ed-software/react-material-symbols

juliolmuller commented 1 year ago

Any plans to include Material Symbols in @mui/icons-material or create a separate package (e.g. @mui/symbols-material) to cover this gap?

oliviertassinari commented 1 year ago

here it is a react based material symbols maybe using the same pattern

@ErreMalote It does work, using https://github.com/marco-prontera/vite-plugin-css-injected-by-js to inject the CSS and Material System font into the page:

Screenshot 2022-12-21 at 23 47 12
import Icon from "react-material-symbols/dist/rounded";

export default function App() {
  return (
    <div className="App">
      <Icon icon="folder" size={24} fill grade={-25} color="red" />
    </div>
  );
}

https://codesandbox.io/s/nifty-poincare-nfduo3?file=/src/App.js


I think that it would make sense to have a first experimental API using the font.

simonecervini commented 1 year ago

I think that it would make sense to have a first experimental API using the font.

In my opinion, the primary issue with using the font is the flash of ligature text on slow internet connections.(https://github.com/vercel/next.js/discussions/42881#discussioncomment-4758644).

Imagine what a <ListItemIcon /> component might look like showing the text "sentiment_very_satisfied" instead of the correct icon.

https://user-images.githubusercontent.com/69400730/214441378-75549bbd-02ff-45b1-a30e-8282f0252454.mov

rodrigonzalz commented 1 year ago

Use font-display: block then it won't show the text before the font is loaded. I've been using Material Symbols with Material UI for months now and 0 problems regarding that.

simonecervini commented 1 year ago

It is true that the font-display: block option is the best choice for icon fonts, however, it does not completely solve the issue. font-display: block gives the font face a longer block period than font-display: swap, font-display-fallback and font-display: optional, but it's typically limited to 2-3 seconds.

You can encounter this problem by simulating slow network conditions in Chrome, such as "Slow 3G" or "Fast 3G" (and obviously disabling the cache).

https://web.dev/font-best-practices/#choose-an-appropriate-font-display-strategy

Screenshot 2023-01-25 at 08 55 34

rodrigonzalz commented 1 year ago

@simonecervini With slow 3g and disable cache the font is not going to be the only thing that takes long to load or that gets partially loaded, the full website will do; so that you get to see the text of the icon is probably the least of your concerns in that scenario.

If I see that the page is loading very slowly, getting partial portions of UI here and there in the span of several seconds, that I see the icon text during that time is not gonna affect me much given the overall state, I can tell the website is loading slowly so it won't surprise to see text replaced by an icon once is done.

Already if you are taking care of slow connections most probably you are already implementing caching, preloading the font, etc; even with all that it will not prevent that to happen 100% if is the user's first time on the page, but it will prevent it for the next times.

I don't see why to make it look like a big deal for something that is not a new issue, that already has ways to be mitigated and that probably you were already handling for other cases (including other fonts).

simonecervini commented 1 year ago

@rodrigonzalz Honestly, I personally see this as a big problem, at least for the use cases I am used to.

We don't all have the same requirements, honestly I very often work with pages that need to perform well even with very slow connections and with this implementation I certainly couldn't use @mui/symbols-material in production (as opposed to the ā€œprevious" @mui/icons-material).

I don't see why to make it look like a big deal for something that is not a new issue, that already has ways to be mitigated and that probably you were already handling for other cases (including other fonts).

Honestly, this is not true. Showing text with a different font during slow loads is very different from showing strings like "sentiment_very_satisfied" instead of specific icons.

It is even worse than loading a blank image replaced by the alt text, because often the ligature text of these icon fonts is completely disconnected from the actual icon description (also because it is not designed for that). MUI itself uses the equivalent of the "history_toggle_off" icon on the pricing page to represent the "work in progress" status. It is objectively not okay to show the text "history_toggle_off" on a pricing page, even in a loading phase, even with very slow connections.

With static pages, fonts, and images loaded correctly (with fallback fonts and blurred placeholder images for example), it is possible to create pages that perform perfectly well even with very slow connections, right from the first load without cache. Therefore, no, it is not true that this is a problem we would probably handle anyway.

Maybe these are not everyone's use cases and the tradeoff is acceptable. I am simply expressing my opinion based on my own experiences and usage.

rodrigonzalz commented 1 year ago

@simonecervini Honestly, I think you are under some misunderstanding and that's why you take it as a big issue.

We don't all have the same requirements, honestly I very often work with pages that need to perform well even with very slow connections and with this implementation I certainly couldn't use @mui/symbols-material in production (as opposed to the ā€œprevious" @mui/icons-material).

Of course we don't all have the same requirements, and as you say, if the use of font icon doesn't work for you then you always have the option to use the svg icons as you are currently doing.

This issue doesn't say anything about replacing the current icons exclusively with the material-symbols font, that somehow svg icons are gone. As stated in the original issue comment:

We will need to update our icons to reflect this change, both for font and SVG icons. It's an important step forward in terms of icon

The whole svg vs font icons tradeoff has been already stated on the documentation since a long time, here. That's why I am saying this is nothing new, neither that such a big issue, you would use what is better for your use case, that's why different options are provided.

simonecervini commented 1 year ago

@rodrigonzalz I understand that this conversation doesn't affect @mui/icons-material at all. If the same flexibility to choose between fonts and SVGs will be maintained for @mui/symbols-material as well, I apologize because I misunderstood.

tryngl commented 1 year ago

Hi there - Was hoping to start using the latest material symbols, as several symbols look new & improved compared to legacy iconography. Great initiative, looking forward to this!

lune-generic-user commented 10 months ago

+1 this would be useful as more and more Material Symbols get added but don't get added to the legacy set. the new set also gives more stylistic flexibility.

tphinney commented 9 months ago

I will note that if somebody doesnā€™t like the ā€œflashā€ of changeover where a whole big ligature collapses to an icon during font loading (FOUT), they could instead reference the icons by codepoints. That would generally result in a single notdef until the icon loads, which might be less disruptive.

I donā€™t mean to suggest this is a perfect solution, just might be a slightly less disruptive choice, as far as the effect of FOUT.

cbreezier commented 9 months ago

One thing that I don't think has been mentioned yet is theming support. The existing material icons respect the text color and font size set by the theme. Any implementation of the Material Symbols should also respect these settings, regardless of whether it's rendered as a font or an svg.

N2D4 commented 5 months ago

In my opinion, the primary issue with using the font is the flash of ligature text on slow internet connections.(vercel/next.js#42881 (comment)).

@simonecervini You can use the codepoints instead (optimally the library would do the transformation):

https://github.com/mui/material-ui/assets/19274317/c68d0333-c5e1-49dd-8ea5-ad1bc41ec3f9

There's some CLS in my video, but there are ways to fix that with a fallback font as well.

I'd like to have fonts over SVG because of the animations, but I'm worried about the 2MB file size if all variants are included (even the 300KB baseline is a lot). Creating an optimized font file at build-time based on whatever icons you imported would be the optimal solution, but that sounds more like a bundler plug-in than a MUI component.

simonecervini commented 5 months ago

In my opinion, the primary issue with using the font is the flash of ligature text on slow internet connections.(vercel/next.js#42881 (comment)).

@simonecervini You can use the codepoints instead (optimally the library would do the transformation):

Screen.Recording.2023-12-07.at.12.18.11.mov There's some CLS in my video, but there are ways to fix that with a fallback font as well.

I'd like to have fonts over SVG because of the animations, but I'm worried about the 2MB file size if all variants are included (even the 300KB baseline is a lot). Creating an optimized font file at build-time based on whatever icons you imported would be the optimal solution, but that sounds more like a bundler plug-in than a MUI component.

@N2D4 I personally ended up creating a custom script that fetches the SVGs I want from fonts.gstatic.com with the font settings I want, optimize them with SVGR, convert them to react components and compile everything into a single large icons.tsx server component.

This approach works very well with server components since it enables you to create a single large file, without sending all the icons to the client. With the same approach you could also create a <Icon id='arrow_forward' /> component that returns the correct icon from the large file without performance issues.

Screenshot 2023-12-07 alle 12 40 30

RubtsovAV commented 3 months ago

Installation

Install the package in your project directory with:

npm install @mui-symbols-material/w400

To install icons of a different weight, simply replace 400 with the desired weight in the installation command.

These components use the MaterialĀ UI's SvgIcon component to render the SVG path for each icon.

If you are not already using MaterialĀ UI in your project, you can add it with:

npm install @mui/material

Usage

Once installed, you can use the icons in your React components:

import React from 'react';
import { 
  FavoriteOutlined, 
  FavoriteRounded, 
  FavoriteSharp, 
  FavoriteFilledOutlined, 
  FavoriteFilledRounded, 
  FavoriteFilledSharp,
} from '@mui-symbols-material/w400'; // Replace 400 with your desired weight

/**
 * Renders all variants of the favorite icon from Material Symbols.
 */
function MyComponent() {
  return (
    <>
      <FavoriteOutlined />
      <FavoriteRounded />
      <FavoriteSharp />
      <FavoriteFilledOutlined />
      <FavoriteFilledRounded />
      <FavoriteFilledSharp />
    </>
  );
}

Available Weights

The following weights are available, providing a range of design options:

Once installed, you can use the icons in your React components. Here's an example showing how to use icons of two different weights:

import React from 'react';
import { FavoriteOutlined as FavoriteRegular } from '@mui-symbols-material/w400'; // Regular weight
import { FavoriteOutlined as FavoriteBold } from '@mui-symbols-material/w700'; // Bold weight

function MyComponent() {
  return (
    <div>
      <FavoriteRegular /> {/* Regular weight icon */}
      <FavoriteBold /> {/* Bold weight icon */}
    </div>
  );
}
Codex- commented 3 months ago

Install the package in your project directory with:

npm install @mui-symbols-material/w400

For transparency, it's worth noting that these packages aren't officially maintained by the mui team but instead @RubtsovAV themself

Repo: https://github.com/RubtsovAV/mui-symbols-material

RubtsovAV commented 2 months ago

@Codex- Thank you. And this is built on the mui-icon package, introducing a fresh collection of Google icons. I believe the MUI team, for version 7, will incorporate symbols, and creating a fork of this package will save them time.