Í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/icons
exporta os respectivos ícones usando a nomeação "PascalCase" (por exemploDeleteForever
,AddAPhoto
). Há três exceções a essa regra de nomenclatura:3d_rotation
exportado comoThreeDRotation
,4k
exportado comoFourK
e360
exportado 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>