Ícones
Orientação e sugestões para usar ícones com o Material-UI.
Material-UI fornece suporte de ícones de três maneiras:
- Padronizados como ícones do Material Design e exportados como componentes do React (ícones SVG).
- Com o componente SvgIcon, um wrapper React para ícones SVG customizados.
- 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/iconsexporta os respectivos ícones usando a nomeação "PascalCase" (por exemploDeleteForever,AddAPhoto). Há três exceções a essa regra de nomenclatura:3d_rotationexportado comoThreeDRotation,4kexportado comoFourKe360exportado comoThreeSixty.
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] }} /><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',
},
},
},
},
});
<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>