Ícones React
Cada ícone do glyphfox é um componente React que renderiza SVG inline. As mesmas props funcionam em todos os ícones, nenhum provider é necessário e os componentes que você não importa nunca chegam ao seu bundle.
Instalação
Os componentes React ficam no pacote principal glyphfox, no ponto de entrada glyphfox/react. O React é uma peer dependency opcional: o pacote funciona com o React 16.8 ou mais recente, porque só precisa de hooks e de forwardRef, e a suíte de testes dele roda com o React 19.
npm install glyphfox
Não há folha de estilo para importar nem plugin de build para adicionar. O pacote traz builds ESM e CommonJS com declarações de tipo, então Vite, webpack, Rspack, esbuild e Parcel usam o pacote sem nenhum ajuste.
Renderize seus primeiros ícones
Cada ícone é exportado com o próprio nome em PascalCase e o sufixo Icon: home vira HomeIcon, arrow-right vira ArrowRightIcon e message-circle vira MessageCircleIcon. Procure um nome no explorador de ícones; a página de cada ícone, como a de arrow right, também mostra a linha do import.
import { HomeIcon, SearchIcon, BellIcon } from 'glyphfox/react'; export function Toolbar() { return ( <nav className="toolbar"> <a href="/"><HomeIcon /> Home</a> <button type="button" aria-label="Search"> <SearchIcon /> </button> <BellIcon size={20} /> </nav> ); }
Sem props, um ícone tem 24 por 24 pixels, é desenhado com stroke="currentColor" (por isso assume a cor do texto do elemento pai) e recebe aria-hidden="true", porque a maioria dos ícones fica ao lado de um rótulo visível. Passe um title quando o ícone for a única coisa que transmite o significado; o guia de acessibilidade mostra os padrões.
Tamanho, cor, peso e estilo
Todo ícone é renderizado em três eixos: peso, cantos e estilo. Eles são props comuns, então podem acompanhar o estado, temas ou breakpoints como qualquer outro valor.
import { FolderIcon, SearchIcon, ArrowRightIcon } from 'glyphfox/react'; export function Axes() { return ( <> <SearchIcon size={32} color="#ff7a1a" /> <SearchIcon weight={1} /> <SearchIcon weight={3} corners="sharp" /> <SearchIcon size={16} weight={1.5} absoluteWeight /> <FolderIcon variant="duotone" secondaryColor="#ff7a1a" /> <FolderIcon variant="solid" /> <ArrowRightIcon rotate={90} /> <ArrowRightIcon mirrorRtl /> </> ); }
sizeaceita um número de pixels ou qualquer medida CSS em forma de string, como"1.25em".weightvai de 1 a 3 na grade de 24. Abaixo de 24 pixels o traço recebe compensação óptica, ficando até 30 por cento mais grosso nos menores tamanhos, então um ícone de 16 pixels mantém a mesma presença de um de 24.absoluteWeightdesliga isso e mantém o traço com exatamenteweightpixels.variant="duotone"usa a segunda camada desenhada à mão quando o ícone tem uma, ou um preenchimento translúcido das formas fechadas.variant="solid"preenche as formas fechadas e recorta as linhas internas como espaço negativo.mirrorRtlespelha os ícones direcionais quando eles são renderizados dentro dedir="rtl", então o mesmo markup funciona nas duas direções.
Ícones por nome
Quando o ícone vem de dados, como um campo de CMS, uma tabela de rotas ou uma configuração do usuário, renderize com Icon e um nome. A prop name aceita a sintaxe de nomes completa, compartilhada por todos os pacotes do glyphfox, então modificadores, fusões e estilos funcionam a partir de uma única string.
import { Icon } from 'glyphfox/react'; export function MenuItem({ item }) { // item.icon could be "settings", "file+check@tr", "cloud&lock:overlap" or "heart/solid" return ( <li> <Icon name={item.icon} size={18} /> {item.label} </li> ); }
Nomes que não foram importados em lugar nenhum são carregados sob demanda com um import dinâmico. O webpack e o esbuild dividem esse import em um chunk pequeno por ícone e, até esse chunk chegar, Icon renderiza um SVG vazio do tamanho certo, para o layout não dar saltos. Um build de produção do Vite deixa esse import intacto dentro de node_modules, então nele o nome fica vazio (o guia de tree shaking tem os detalhes). Em qualquer bundler a solução é a mesma: registre uma única vez, na inicialização, os dados dos nomes que você renderiza a partir de strings, e eles passam a renderizar de forma síncrona, já na primeira pintura e no servidor:
import { registerIcons } from 'glyphfox/react'; import { iconSettings, iconFile, iconCloud, iconLock } from 'glyphfox'; registerIcons([iconSettings, iconFile, iconCloud, iconLock]);
Os exports de dados (iconSettings, iconArrowRight...) vêm do ponto de entrada principal glyphfox e passam por tree shaking como os componentes: importar um deles custa algumas centenas de bytes. Importar um componente como SettingsIcon também registra os dados dele.
Modificadores e fusões
Um modificador é um selo pequeno num canto de qualquer ícone: plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down ou dot. O ícone de baixo é recortado em volta do selo com um espaço de recorte, então as linhas nunca se tocam, em qualquer peso.
import { FileIcon, CloudIcon, Fusion } from 'glyphfox/react'; export function Status({ saved, syncing }) { return ( <> <FileIcon modifier={saved ? 'check' : undefined} /> <CloudIcon modifier={syncing ? 'sync' : undefined} modifierCorner="top-right" /> <Fusion icons={['cloud', 'lock']} layout="overlap" gap={1} /> <Fusion icons={['shield', 'heart']} layout="inside" /> </> ); }
Fusion combina de 2 a 10 ícones num ícone novo que continua seguindo as regras dos ícones: um único peso, a grade de 24 e a caixa de margem. Os layouts são overlap, side, stack, grid, orbit, badge e inside; gap define o espaço de recorte em unidades da grade, e scale e offsets fazem o ajuste fino de cada parte. O Fusion aceita todas as props compartilhadas, então um ícone fundido pode ser duotone, animado ou ter um rótulo como qualquer outro.
Morph e estados vivos
Três ferramentas cuidam do movimento. MorphIcon se transforma sempre que o name muda. morphTo, em qualquer ícone, faz o ícone se transformar no destino quando o trigger dispara. animate toca um preset (draw, pop, wiggle, spin, pulse, bounce ou shake) na montagem, no hover, no clique ou enquanto active for verdadeiro.
import { MorphIcon, MenuIcon, BellIcon, HeartIcon } from 'glyphfox/react'; export function Motion({ open, copied, hasNews, liked }) { return ( <> <MorphIcon name={copied ? 'check' : 'copy'} duration={300} /> <MenuIcon morphTo={open ? 'x' : undefined} /> <BellIcon animate="shake" trigger="state" active={hasNews} /> <HeartIcon animate="pop" trigger="click" variant={liked ? 'solid' : 'outline'} /> </> ); }
Para um renderizador próprio, useMorph(name, { duration }) devolve os dados do ícone no frame atual, que você pode passar para Icon pela prop icon ou para o seu próprio código de desenho. Toda animação respeita prefers-reduced-motion. O guia de ícones animados explica os presets, os gatilhos e os pares de morph ajustados à mão.
import { Icon, useMorph } from 'glyphfox/react'; export function PlayButton({ playing }) { const frame = useMorph(playing ? 'pause' : 'play', { duration: 250 }); return frame ? <Icon icon={frame.icon} variant={frame.variant} size={28} /> : null; }
Refs, className, style e eventos
Os componentes usam forwardRef, então uma ref aponta para o elemento <svg> renderizado. className é adicionado depois das classes embutidas glyphfox glyphfox-NAME, style é repassado como está e qualquer outro atributo SVG ou handler de evento (onClick, data-*, aria-*, id) vai direto para o elemento.
import { useRef } from 'react'; import { HeartIcon } from 'glyphfox/react'; export function Like({ onLike }) { const ref = useRef(null); const like = () => { ref.current?.animate([{ transform: 'scale(1)' }, { transform: 'scale(1.25)' }, { transform: 'scale(1)' }], 240); onLike(); }; return ( <button type="button" onClick={like}> <HeartIcon ref={ref} className="like-icon" style={{ color: 'var(--accent)' }} /> Like </button> ); }
Um aria-label passado dessa forma também marca o ícone como significativo: o componente troca aria-hidden por role="img" automaticamente.
TypeScript
Os tipos vêm com o pacote. GlyphIconComponent é o tipo de todo componente de ícone, GlyphProps são as props dele (as props compartilhadas mais qualquer atributo SVG) e IconName, do ponto de entrada principal, é a união de todos os nomes de ícones, o que garante autocompletar em Icon e nos seus próprios dados.
import type { IconName } from 'glyphfox'; import { Icon, HomeIcon, SettingsIcon, type GlyphIconComponent } from 'glyphfox/react'; type NavItem = { label: string; href: string; icon: GlyphIconComponent }; const items: NavItem[] = [ { label: 'Home', href: '/', icon: HomeIcon }, { label: 'Settings', href: '/settings', icon: SettingsIcon }, ]; export function Nav() { return ( <nav> {items.map(({ label, href, icon: ItemIcon }) => ( <a key={href} href={href}> <ItemIcon size={18} /> {label} </a> ))} </nav> ); } export function Badge({ name }: { name: IconName }) { return <Icon name={name} variant="duotone" />; }
Imports e tamanho do bundle
Imports nomeados de glyphfox/react passam por tree shaking: cada ícone é um módulo próprio, criado com uma anotação pure, e o pacote declara quais arquivos têm efeitos colaterais. Imports profundos como glyphfox/react/icons/home carregam um único módulo de ícone diretamente, o que ajuda ferramentas que não fazem tree shaking e evita que os servidores de desenvolvimento toquem no índice completo.
import { HomeIcon } from 'glyphfox/react/icons/home'; import FileIcon from 'glyphfox/react/icons/file'; // default export works too
O guia de tree shaking mostra, com medições, o que quebra o tree shaking, quanto custa o runtime compartilhado e por que a saída do build traz um chunk minúsculo por ícone.
Props
Todos os componentes de ícone, além de Icon, Fusion e MorphIcon, aceitam as mesmas props. Elas têm os mesmos nomes e o mesmo significado no Vue, no Svelte, no Angular, no web component e no toSvg, então um valor copiado do estúdio funciona em qualquer lugar.
| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
size | number, string | 24 | Largura e altura; números são pixels. |
color | string | currentColor | Cor principal. |
secondaryColor | string | color | Cor da camada duotone e do preenchimento sólido. |
secondaryOpacity | number | 0.3 / 1 | Opacidade da camada duotone ou do preenchimento sólido. |
weight | number | 2 | Traço de 1 a 3 na grade de 24, com compensação óptica abaixo de 24 px. |
absoluteWeight | boolean | false | Mantém o traço com weight pixels em qualquer tamanho. |
corners | round, sharp | round | Junções e pontas redondas ou retas. |
variant | outline, duotone, solid | outline | Eixo de estilo; o sólido vem das formas fechadas. |
rotate | number | 0 | Rotação em graus. |
flipX | boolean | false | Espelha na horizontal. |
flipY | boolean | false | Espelha na vertical. |
mirrorRtl | boolean | false | Espelha em layouts da direita para a esquerda. |
animate | draw, pop, wiggle, spin, pulse, bounce, shake | nenhum | Animação de estado vivo. |
trigger | mount, hover, click, state | mount | Quando a animação ou o morph acontece. |
active | boolean | false | O estado para o gatilho state. |
duration | number (ms) | por animação | Duração da animação ou do morph. |
delay | number (ms) | 0 | Atraso da animação ou do morph. |
loop | boolean, number | false | Repete para sempre ou um número de vezes (spin e pulse repetem por padrão). |
modifier | plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dot | nenhum | Selo com espaço de recorte automático. |
modifierCorner | top-left, top-right, bottom-left, bottom-right | bottom-right | Canto do selo. |
morphTo | name, data | nenhum | Destino do morph; o gatilho decide quando aparece. |
title | string | nenhum | Nome acessível: title, role img e aria-label. |
decorative | boolean | true sem title | Esconde o ícone das tecnologias assistivas. |
Icon e MorphIcon também aceitam name (qualquer forma da sintaxe de nomes) ou icon (dados de ícone). Fusion aceita icons, layout, gap, scale e offsets.
Armadilhas comuns
Iconaparece vazio no início- Um nome que ainda não foi registrado é buscado com um import dinâmico, então a primeira renderização (e a renderização no servidor) é um SVG vazio. Importe o componente ou chame
registerIconscom os dados de todos os nomes que você renderiza por string. - Server Components do Next.js
- Os componentes usam hooks e o pacote não tem a diretiva
"use client", então um Server Component não consegue renderizá-los diretamente. O guia de Next.js mostra a correção com um único arquivo e uma opção sem nenhum JavaScript. - Colorir com
fill - Os ícones são traços sobre
fill="none". Passarfillpreenche todas as formas, o que raramente é o que você quer. Usecolor(ou ocolordo CSS num elemento pai) para o traço evariant="solid"para formas preenchidas. - CSS global sobrescreve o peso
- Uma regra de folha de estilo como
svg { stroke-width: 1.5 }tem prioridade sobre o atributo SVG que carrega o eixo de peso, inclusive a compensação óptica. Limite o escopo dessas regras ou use a propweight. - Tamanhos relativos ficam sem compensação óptica
- A compensação precisa saber o tamanho em pixels. Com
size="1em"o traço fica no peso nominal, o que pode parecer fino em textos pequenos; passe um número de pixels onde isso fizer diferença, ou umweightum pouco maior. - Chamar
createIcondurante a renderização createIcon(data)transforma os seus próprios dados de ícone em um componente com todas as props. Chame uma única vez, no nível do módulo: chamar dentro de um componente cria um novo tipo de componente a cada renderização e remonta o SVG.import *com chave dinâmicaIcons[name]num import de namespace mantém todos os ícones no bundle. PrefiraIconcom um nome, que carrega só o que é renderizado.
Perguntas frequentes
Posso usar meus próprios ícones com as mesmas props?
Sim. createIcon(data), de glyphfox/react, recebe dados de ícone (name, body, tags, categories) e devolve um componente com todas as props compartilhadas, incluindo peso, os estilos duotone e solid, modificadores e morph. Desenhe o ícone no editor do estúdio ou converta um SVG existente com o Fox-ify, para que ele siga as mesmas regras de grade e de traço.
Como definir um tamanho ou peso padrão para todos os ícones?
O pacote React não tem provider, então o caminho mais comum é um wrapper pequeno, como const NavIcon = (props) => <Icon size={20} weight={1.75} {...props} />. A cor não exige nada: os ícones seguem o color do CSS do elemento pai.