Frameworks

Í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.

terminal
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.

Toolbar.jsx
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.

Axes.jsx
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 />
    </>
  );
}
  • size aceita um número de pixels ou qualquer medida CSS em forma de string, como "1.25em".
  • weight vai 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. absoluteWeight desliga isso e mantém o traço com exatamente weight pixels.
  • 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.
  • mirrorRtl espelha os ícones direcionais quando eles são renderizados dentro de dir="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.

MenuItem.jsx
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:

icons.js
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.

Status.jsx
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.

Motion.jsx
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.

CustomMorph.jsx
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.

Like.jsx
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.

nav.tsx
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.

deep-imports.js
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.

PropTipoPadrãoDescrição
sizenumber, string24Largura e altura; números são pixels.
colorstringcurrentColorCor principal.
secondaryColorstringcolorCor da camada duotone e do preenchimento sólido.
secondaryOpacitynumber0.3 / 1Opacidade da camada duotone ou do preenchimento sólido.
weightnumber2Traço de 1 a 3 na grade de 24, com compensação óptica abaixo de 24 px.
absoluteWeightbooleanfalseMantém o traço com weight pixels em qualquer tamanho.
cornersround, sharproundJunções e pontas redondas ou retas.
variantoutline, duotone, solidoutlineEixo de estilo; o sólido vem das formas fechadas.
rotatenumber0Rotação em graus.
flipXbooleanfalseEspelha na horizontal.
flipYbooleanfalseEspelha na vertical.
mirrorRtlbooleanfalseEspelha em layouts da direita para a esquerda.
animatedraw, pop, wiggle, spin, pulse, bounce, shakenenhumAnimação de estado vivo.
triggermount, hover, click, statemountQuando a animação ou o morph acontece.
activebooleanfalseO estado para o gatilho state.
durationnumber (ms)por animaçãoDuração da animação ou do morph.
delaynumber (ms)0Atraso da animação ou do morph.
loopboolean, numberfalseRepete para sempre ou um número de vezes (spin e pulse repetem por padrão).
modifierplus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dotnenhumSelo com espaço de recorte automático.
modifierCornertop-left, top-right, bottom-left, bottom-rightbottom-rightCanto do selo.
morphToname, datanenhumDestino do morph; o gatilho decide quando aparece.
titlestringnenhumNome acessível: title, role img e aria-label.
decorativebooleantrue sem titleEsconde 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

Icon aparece 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 registerIcons com 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". Passar fill preenche todas as formas, o que raramente é o que você quer. Use color (ou o color do CSS num elemento pai) para o traço e variant="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 prop weight.
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 um weight um pouco maior.
Chamar createIcon durante 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âmica
Icons[name] num import de namespace mantém todos os ícones no bundle. Prefira Icon com 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.

Ícones deste guia