Pular para o conteúdo

Ícones

Orientação e sugestões para usar ícones com o Material-UI.

Material-UI fornece suporte de ícones de três maneiras:

  1. Padronizados como ícones do Material Design e exportados como componentes do React (ícones SVG).
  2. Com o componente SvgIcon, um wrapper React para ícones SVG customizados.
  3. Com o componente Icon, um wrapper React para ícones de fonte customizados.

Ícones Material

O Material Design padronizou mais de 1.100 ícones oficiais, cada um em cinco "temas" diferentes (veja abaixo). Para cada ícone SVG, exportamos o respectivo componente React do pacote @material-ui/icons. Você pode pesquisar na lista completa destes ícones.

Instalação

Instale o pacote no diretório do seu projeto com:

// usando npm
npm install @material-ui/icons

// usando yarn
yarn add @material-ui/icons

Esses componentes usam o componente SvgIcon do Material-UI para renderizar o caminho SVG de cada ícone, e por isso tem uma dependência com @materialui/core.

Se você ainda não estiver usando Material-UI no seu projeto, você pode adicioná-lo com:

// usando npm
npm install @material-ui/core

// usando yarn
yarn add @material-ui/core

Uso

Importe ícones usando uma destas duas opções:

  • Opção 1:

    import AccessAlarmIcon from '@material-ui/icons/AccessAlarm';
    import ThreeDRotation from '@material-ui/icons/ThreeDRotation';
  • Opção 2:

    import { AccessAlarm, ThreeDRotation } from '@material-ui/icons';

O mais seguro para o tamanho do pacote é a opção 1, mas alguns desenvolvedores preferem a opção 2. Certifique-se de seguir o guia minimizando o tamanho do pacote antes de usar a segunda abordagem.

Cada ícone Material também tem um "tema": Filled (padrão), Outlined, Rounded, Two-tone, e Sharp. Para importar o componente de ícone com um tema diferente do padrão, acrescente o nome do tema ao nome do ícone. Por exemplo, para usar o ícone @material-ui/icons/Delete, temos:

  • Tema Filled (preenchido que é o padrão) é exportado como @material-ui/icons/Delete,
  • Tema Outlined (contornado) é exportado como @material-ui/icons/DeleteOutlined,
  • Tema Rounded (arredondado) é exportado como @material-ui/icons/DeleteRounded,
  • Tema Two tone (dois tons) é exportado como @material-ui/icons/DeleteTwoTone,
  • Tema Sharp (pontiagudo) é exportado como @material-ui/icons/DeleteSharp.

Nota: A especificação Material Design nomeia os ícones usando a nomeação "snake_case" (por exemplo, delete_forever, add_a_photo), enquanto @material-ui/icons exporta os respectivos ícones usando a nomeação "PascalCase" (por exemplo DeleteForever, AddAPhoto). Há três exceções a essa regra de nomenclatura: 3d_rotation exportado como ThreeDRotation, 4k exportado como FourKe 360 exportado como ThreeSixty.

Filled

Outlined

Rounded

Two Tone

Sharp

Edge-cases

Testando

Para fins de teste, cada ícone exposto do @material-ui/icons tem um atributo data-testid com o nome do ícone. Por exemplo:

import DeleteIcon from '@material-ui/icons/Delete';

tem o seguinte atributo assim que montado:

<svg data-testid="DeleteIcon"></svg>

SvgIcon

Se você precisa de um ícone SVG customizado (não disponível nos ícones Material) você pode usar encapsular com SvgIcon. Este componente estende o elemento nativo <svg>:

  • Ele vem internamente com a acessibilidade.
  • Os elementos SVG devem ser dimensionados para uma visualização de 24x24px, de modo que o ícone resultante possa ser usado como está, ou incluído como filho para outros componentes de Material-UI que usam ícones. (Isso pode ser customizado com o atributo viewBox).
  • Por padrão, o componente herda a cor atual. Opcionalmente, você pode aplicar uma das cores do tema usando a propriedade color.
function HomeIcon(props) {
  return (
    <SvgIcon {...props}>
      <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
    </SvgIcon>
  );
}

Cor

<HomeIcon />
<HomeIcon color="primary" />
<HomeIcon color="secondary" />
<HomeIcon color="action" />
<HomeIcon color="disabled" />
<HomeIcon style={{ color: green[500] }} />

Tamanho

<HomeIcon fontSize="small" />
<HomeIcon />
<HomeIcon fontSize="large" />
<HomeIcon style={{ fontSize: 40 }} />

Propriedade Componente

Você pode usar o SvgIcon para encapsular seus ícones, mesmo que estes estejam salvos no formato .svg. A biblioteca svgr possui loaders para importar arquivos SVG e usá-los como componentes React. Por exemplo, com webpack:

// webpack.config.js
{
  test: /\.svg$/,
  use: ['@svgr/webpack'],
}

// ---
import StarIcon from './star.svg';

<SvgIcon component={StarIcon} viewBox="0 0 600 476.6" />

Também é possível usá-lo com "url-loader" ou "file-loader". Esta é a abordagem usada pelo Create React App.

// webpack.config.js
{
  test: /\.svg$/,
  use: ['@svgr/webpack', 'url-loader'],
}

// ---
import { ReactComponent as StarIcon } from './star.svg';

<SvgIcon component={StarIcon} viewBox="0 0 600 476.6" />

createSvgIcon

O componente utilitário createSvgIcon é usado para criar ícones Material. Ele pode ser usado para encapsular um caminho SVG com um componente SvgIcon.

const HomeIcon = createSvgIcon(
  <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />,
  'Home',
);
<HomeIcon />
<HomeIcon color="primary" />

Fonte Awesome

Se você descobrir que há problemas de leiaute ao usar FontAwesomeIcon de @fortawesome/react-fontawesome, você pode tentar passar os dados SVG da Font Awesome diretamente para SvgIcon.

Fonte Awesome pode ser usada com o componente Icon da seguinte forma:

Nota: mdi-material-ui já agrupou cada um desses ícones SVG com o componente SvgIcon, para que você não precise fazer isso.

A propriedade fullWidth de FontAwesomeIcon também pode ser usada para aproximar as dimensões corretas, mas não é garantida.

Fonte Material icons

MDI

O site materialdesignicons.com fornece mais de 2.000 ícones. Para o ícone desejado, copie o SVG path que eles fornecem, e use-o como elemento filho no componente SvgIcon, ou com createSvgIcon().

Nota: A biblioteca mdi-material-ui já agrupou cada um desses ícones SVG com o componente SvgIcon, para que você não precise fazer isso.

Ícone (ícones de fonte)

O componente Icon exibirá um ícone de qualquer fonte de ícone que suporte ligadura tipográfica (ligatures). Como pré-requisito, você deve incluir uma em seu projeto, como a Material icon font. Para usar um ícone, simplesmente coloque o nome do ícone (font ligature) com o componente Icon, por exemplo:

import Icon from '@material-ui/core/Icon';

<Icon>star</Icon>

Por padrão, um ícone herdará a cor do texto atual. Opcionalmente, você pode definir a cor do ícone usando uma das propriedades de cor do tema: primary, secondary, action, erro & disabled.

Fonte Material icons

Icon irá por padrão definir o nome de classe base correto para a fonte Material Icons (variante filled). Tudo que você precisa fazer é carregar a fonte, por exemplo, através do Google Web Fonts:

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<Icon>add_circle</Icon>
<Icon color="primary">add_circle</Icon>
<Icon style={{ color: green[500] }}>add_circle</Icon>
<Icon fontSize="small">add_circle</Icon>
<Icon style={{ fontSize: 30 }}>add_circle</Icon>

Fonte customizada

Para outras fontes, você pode customizar o nome de classe base usando a propriedade baseClassName. Por exemplo, você pode exibir ícones de dois tons com Material Design:

import Icon from '@material-ui/core/Icon';

<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css?family=Material+Icons+Two+Tone"
  // Importe a variante MD de dois tons                           ^^^^^^^^
/>;
<Icon baseClassName="material-icons-two-tone">add_circle</Icon>

Nome da classe base global

Modificar a propriedade baseClassName para cada uso feito do componente é repetitivo. Você pode alterar a propriedade padrão globalmente com o tema

const theme = createMuiTheme({
  components: {
    MuiIcon: {
      defaultProps: {
        // Substitui o valor padrão `material-icons`.
        baseClassName: 'material-icons-two-tone',
      },
    },
  },
});

Então, você pode usar a fonte de dois tons diretamente:

<Icon>add_circle</Icon>

Fonte Awesome

Fonte Awesome pode ser usada com o componente Icon da seguinte forma:

<Icon baseClassName="fas" className="fa-plus-circle" />
<Icon baseClassName="fas" className="fa-plus-circle" color="primary" />
<Icon
  baseClassName="fas"
  className="fa-plus-circle"
  style={{ color: green[500] }}
/>
<Icon baseClassName="fas" className="fa-plus-circle" fontSize="small" />
<Icon
  baseClassName="fas"
  className="fa-plus-circle"
  style={{ fontSize: 30 }}
/>

Note que os ícones da fonte Awesome não foram projetados como os ícones do Material Design (compare as duas demonstrações anteriores). Os ícones fa são cortados para usar todo o espaço disponível. Você pode ajustar isso com uma sobrescrita global:

const theme = createMuiTheme({
  components: {
    MuiIcon: {
      styleOverrides: {
        root: {
          // Corresponde 24px = 3 * 2 + 1.125 * 16
          boxSizing: 'content-box',
          padding: 3,
          fontSize: '1.125rem',
        },
      },
    },
  },
});
Call me
Call me
<ThemeProvider theme={theme}>
  <Chip icon={<MdPhone />} label="Call me" />
  <Chip icon={<Icon className="fas fa-phone-alt" />} label="Call me" />
</ThemeProvider>

Fonte vs SVG. Qual abordagem usar?

Ambas as abordagens funcionam bem, no entanto, existem algumas diferenças sutis, especialmente em termos de desempenho e qualidade de renderização. Sempre que possível, utlize o SVG, pois permite a divisão do código, suporta mais ícones e renderiza mais rápido e melhor.

Para maiores detalhes, dê uma olhada no porque o GitHub migrou ícones de fonte para ícones SVG.

Acessibilidade

Ícones podem transmitir todos os tipos de informações significativas, então é importante garantir que eles estejam apropriadamente acessíveis. Há dois casos de uso que você deve considerar:

  • Ícones decorativos que são usados apenas para reforço visual ou de marca. Se eles forem removidos da página, os usuários ainda entenderiam e poderiam usar sua página.
  • Ícones Semânticos são aqueles que você usa para transmitir significado, em vez de apenas pura decoração. Isso inclui ícones sem texto ao lado deles que são usados como controles interativos — botões, elementos de forma, toggles, etc.

Ícones decorativos

Se seus ícones são puramente decorativos, você já terminou! O atributo aria-hidden=true foi adicionado para que seus ícones estejam adequadamente acessíveis (invisíveis).

Ícones semânticos

Ícones SVG semânticos

Você deve incluir a propriedade titleAccess com um valor significativo. O atributo role="img" e o elemento <title> foram adicionados para que seus ícones sejam corretamente acessíveis.

No caso de elementos interativos focalizáveis, por exemplo, quando usado com um botão de ícone, você pode usar a propriedade aria-label:

import IconButton from '@material-ui/core/IconButton';
import SvgIcon from '@material-ui/core/SvgIcon';

// ...

<IconButton aria-label="deletar">
  <SvgIcon>
    <path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z" />
  </SvgIcon>
</IconButton>

Ícones de fonte semânticos

Você precisa fornecer um texto alternativo que só seja visível para tecnologia assistiva.

import Icon from '@material-ui/core/Icon';
import Typography from '@material-ui/core/Typography';

// ...

<Icon>add_circle</Icon>
<Typography variant="srOnly">Crie um usuário</Typography>

Referência