Ícones no Svelte 5
O glyphfox/svelte traz um componente Svelte 5 para cada ícone, além de Icon, Fusion e MorphIcon, com as mesmas props de todos os outros pacotes do glyphfox.
Instalação
npm install glyphfox
Os componentes são arquivos-fonte .svelte que a sua aplicação compila, então o build precisa do Svelte 5 e do compilador dele, normalmente via vite-plugin-svelte, que todo projeto SvelteKit já tem. Eles são escritos com runes como $props e $state, por isso o Svelte 4 não consegue compilá-los.
O svelte 5 é uma peer dependency opcional do glyphfox: você só precisa dele quando importa glyphfox/svelte. O pacote expõe esse ponto de entrada sob a condição de export svelte, que o vite-plugin-svelte usa para reconhecer uma biblioteca Svelte e compilar os componentes dela para o navegador e para o servidor.
Use os componentes
<script> import { HomeIcon, SearchIcon, BellIcon } from 'glyphfox/svelte'; let { unread = 0 } = $props(); </script> <nav class="toolbar"> <a href="/" aria-label="Home"><HomeIcon /></a> <SearchIcon size={20} weight={1.5} class="muted" /> <BellIcon variant="duotone" secondaryColor="#ff7a1a" modifier={unread ? 'dot' : undefined} /> </nav>
Cada ícone é um componente com o nome do ícone em PascalCase e o sufixo Icon: arrow-right vira ArrowRightIcon, loader-circle vira LoaderCircleIcon. As props usam os nomes em camelCase, exatamente como no JavaScript, porque o Svelte passa as props para os componentes do jeito que foram escritas.
class e style são aplicados ao svg, e qualquer outro atributo, como aria-*, data-* ou id, é repassado a ele via spread. No Svelte 5, handlers de evento são props: onclick, onmouseenter e onmouseleave são repassados e continuam rodando quando o ícone tem um gatilho de click ou hover.
Os traços usam currentColor, então o ícone segue o color do CSS do elemento pai. A prop color define uma cor fixa no svg.
Peso, cantos e estilo
weight define o traço de 1 a 3, corners alterna entre junções redondas e retas, e variant escolhe outline, duotone ou solid. Abaixo de 24 px o traço fica um pouco mais grosso para que ícones pequenos mantenham presença; absoluteWeight mantém o valor exato.
<script> import { FolderIcon } from 'glyphfox/svelte'; </script> <FolderIcon weight={1} /> <FolderIcon weight={3} corners="sharp" /> <FolderIcon variant="duotone" secondaryColor="#ff7a1a" /> <FolderIcon variant="solid" /> <FolderIcon size={16} weight={1.5} absoluteWeight />
Icon, modificadores e fusão
Icon renderiza qualquer spec da sintaxe de nomes: um nome, um selo modificador (file+check, com @tl, @tr, @bl ou @br para o canto), uma fusão (cloud&lock:overlap) ou um estilo (heart/solid). Fusion recebe uma lista de nomes e um layout: overlap, side, stack, grid, orbit, badge ou inside.
Os componentes de ícone trazem os próprios dados: cada um registra o seu ícone num bloco <script module>. Um nome dentro de uma string não tem nenhum import por trás, então registre esses nomes uma vez com registerIcons. Os selos modificadores são desenhados pelo motor e não precisam de registro.
import { registerIcons } from 'glyphfox/svelte'; import file from 'glyphfox/icons/file'; import cloud from 'glyphfox/icons/cloud'; import lock from 'glyphfox/icons/lock'; import menu from 'glyphfox/icons/menu'; import x from 'glyphfox/icons/x'; import play from 'glyphfox/icons/play'; import pause from 'glyphfox/icons/pause'; // Every name used in a string: Icon, Fusion, MorphIcon, morphStore and morphTo. registerIcons([file, cloud, lock, menu, x, play, pause]);
<script> import './lib/icons.js'; import { Icon, Fusion } from 'glyphfox/svelte'; let { saved = false } = $props(); </script> <Icon name={saved ? 'file+check' : 'file'} /> <Icon name="file+alert@tr" variant="duotone" /> <Fusion icons={['cloud', 'lock']} layout="overlap" gap={1} />
Importe o módulo de registro no seu arquivo de entrada ou no componente raiz. Um componente também pode registrar ícones no próprio bloco <script module>, que roda uma vez quando o módulo carrega, e não uma vez por instância.
MorphIcon, morphTo e morphStore
MorphIcon anima sempre que o name muda, o que combina naturalmente com $state:
<script> import { MorphIcon } from 'glyphfox/svelte'; let open = $state(false); </script> <button type="button" aria-label="Menu" aria-expanded={open} onclick={() => (open = !open)}> <MorphIcon name={open ? 'x' : 'menu'} duration={300} /> </button>
Qualquer componente de ícone também aceita morphTo com um gatilho: click alterna a cada clique, hover acompanha o ponteiro, state acompanha active e o padrão, mount, faz o morph uma vez depois da montagem.
<script> import { HeartIcon, PlayIcon } from 'glyphfox/svelte'; let { playing = false } = $props(); </script> <HeartIcon morphTo="heart/solid" trigger="click" /> <PlayIcon morphTo="pause" trigger="state" active={playing} />
morphStore(initial, options) é uma store para renderização própria. Chame set(name) para iniciar um morph e leia $store, um frame com icon e variant que você pode passar para Icon.
<script> import './lib/icons.js'; import { Icon, morphStore } from 'glyphfox/svelte'; const frame = morphStore('play', { duration: 250 }); let playing = $state(false); function toggle() { playing = !playing; frame.set(playing ? 'pause' : 'play'); } </script> <button type="button" aria-label="Play" aria-pressed={playing} onclick={toggle}> {#if $frame}<Icon icon={$frame.icon} variant={$frame.variant} />{/if} </button>
Pares ajustados à mão cobrem menu para x, play para pause, plus para check, sun para moon, eye para eye-off, bell para bell-ring, heart para heart/solid, copy para check, lock para unlock e wifi para wifi-off. Os outros pares se transformam com um pareamento automático.
Animações guiadas por estado
Os estados vivos são presets que entendem o ícone: draw desenha os traços na ordem do desenho, shake balança a partir do topo, e pop, wiggle, spin, pulse e bounce completam o conjunto. Com trigger="state", uma animação toca enquanto active for verdadeiro, então ela acompanha as suas runes diretamente.
<script> import { BellIcon, LoaderCircleIcon, SparklesIcon } from 'glyphfox/svelte'; let { hasNews = false, loading = false } = $props(); </script> <BellIcon animate="shake" trigger="state" active={hasNews} /> {#if loading}<LoaderCircleIcon animate="spin" />{/if} <SparklesIcon animate="draw" trigger="hover" />
Cada preset é uma pequena folha de estilo dentro do svg, então não precisa de import de CSS e é desativado para visitantes que preferem movimento reduzido. O guia de ícones animados cobre durações, atrasos e loops.
Imports profundos e tipos
O glyphfox/svelte reexporta todos os componentes, e os builds de produção descartam os que você não importa. Um import profundo resolve para um único arquivo .svelte, o que limita o código que o compilador e o servidor de desenvolvimento enxergam ao que você usa:
<script> import FoxIcon from 'glyphfox/svelte/icons/fox'; </script> <FoxIcon size={32} variant="duotone" title="glyphfox" />
Os tipos vêm com o pacote. Todo componente é um Component<GlyphProps>, em que GlyphProps são as props compartilhadas mais qualquer atributo SVG, então um wrapper tipado pode repassar tudo:
<script lang="ts"> import { Icon, type GlyphProps } from 'glyphfox/svelte'; import type { IconName } from 'glyphfox'; let { name, ...rest }: GlyphProps & { name: IconName } = $props(); </script> <Icon {name} weight={1.75} {...rest} />
Nomes tipados como IconName são verificados em tempo de compilação, mas ainda precisam ser registrados para renderizar: veja as armadilhas abaixo e o guia de tree shaking.
Props
Todos os componentes de ícone, além de Icon, Fusion e MorphIcon, aceitam as props compartilhadas, em camelCase.
| 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 acrescenta name, icon (dados de ícone) e gap. Fusion acrescenta icons, layout, gap, scale e offsets. MorphIcon acrescenta name e icon. O conteúdo filho é renderizado dentro do svg.
Armadilhas comuns
- Props em kebab-case não fazem nada
- No Svelte,
secondary-color="#ff7a1a"não é a propsecondaryColor: ele é repassado ao svg como um atributo comum, e o ícone mantém o padrão. Use os nomes em camelCase em todo lugar. - Nomes que funcionam em desenvolvimento e somem em produção
- Durante o desenvolvimento, o Vite faz o pre-bundle do pacote e todo nome é resolvido. Um build de produção mantém só o que você importa, e o Vite não inclui no bundle o carregador sob demanda que fica dentro de
node_modules, então nomes não registrados emIcon,Fusion,MorphIcon,morphToemorphStorerenderizam um svg vazio. Registre esses nomes. - morphStore criada antes do registro
morphStoreresolve um nome quando você chamaset. Se o nome não estiver registrado nesse momento, ela fica esperando o carregador. Importe o módulo de registro antes de criar a store, como no exemplo acima.- Imports com asterisco e buscas dinâmicas
import * as icons from 'glyphfox/svelte'comicons[name]mantém todos os componentes no bundle. Monte um mapa com os componentes de que você precisa ou useIconcom nomes registrados.
Perguntas frequentes
Posso usar o glyphfox num projeto Svelte 4?
Não com glyphfox/svelte, que precisa do compilador do Svelte 5. Num app Svelte 4, o web component <glyph-fox> funciona com as mesmas props como atributos; veja o guia de web components.
Os componentes precisam do SvelteKit?
Não. Qualquer configuração de Svelte 5 que compile arquivos .svelte funciona, como o Vite puro com vite-plugin-svelte. O SvelteKit acrescenta renderização no servidor e pré-renderização, explicadas no guia de SvelteKit.