Iconos para React
Cada icono de glyphfox es un componente de React que renderiza SVG en línea. Las mismas props sirven para todos los iconos, no hace falta ningún proveedor y los componentes que no importas nunca llegan a tu bundle.
Instalación
Los componentes de React están en el paquete principal glyphfox, bajo el punto de entrada glyphfox/react. React es una peer dependency opcional: el paquete funciona con React 16.8 y versiones posteriores porque solo necesita hooks y forwardRef, y su conjunto de pruebas se ejecuta con React 19.
npm install glyphfox
No hay que importar ninguna hoja de estilos ni agregar ningún plugin de compilación. El paquete incluye compilaciones ESM y CommonJS con declaraciones de tipos, así que Vite, webpack, Rspack, esbuild y Parcel lo usan tal cual.
Renderiza tus primeros iconos
Cada icono se exporta con su nombre en PascalCase y el sufijo Icon: home se convierte en HomeIcon, arrow-right en ArrowRightIcon y message-circle en MessageCircleIcon. Busca un nombre en el explorador de iconos; la página de cada icono, como la de arrow right, también muestra la línea de importación.
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> ); }
Sin props, un icono mide 24 por 24 píxeles, se dibuja con stroke="currentColor" (así toma el color del texto de su elemento padre) y se marca con aria-hidden="true", porque la mayoría de los iconos aparecen junto a una etiqueta visible. Dale un title cuando el icono sea lo único que transmite el significado; la guía de accesibilidad explica los patrones.
Tamaño, color, peso y estilo
Cada icono se renderiza según tres ejes: peso, esquinas y estilo. Son props normales, así que pueden variar según el estado, los temas o los breakpoints, como cualquier otro 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 /> </> ); }
sizeacepta un número de píxeles o cualquier longitud CSS en forma de cadena, como"1.25em".weightva de 1 a 3 en la cuadrícula de 24. Por debajo de 24 píxeles, el trazo se compensa ópticamente, hasta un 30 por ciento más grueso en los tamaños más pequeños, para que un icono de 16 píxeles conserve la misma presencia que uno de 24.absoluteWeightdesactiva esa compensación y mantiene el trazo exactamente enweightpíxeles.variant="duotone"usa la segunda capa dibujada a mano si el icono la tiene o, si no, un relleno translúcido de sus formas cerradas.variant="solid"rellena las formas cerradas y recorta las líneas interiores como espacio negativo.mirrorRtlrefleja los iconos direccionales cuando se renderizan dentro dedir="rtl", así que el mismo marcado funciona en ambas direcciones.
Iconos por nombre
Cuando el icono viene de los datos, como un campo de un CMS, una tabla de rutas o una preferencia del usuario, renderízalo con Icon y un nombre. La prop name acepta la sintaxis de nombres completa que comparten todos los paquetes de glyphfox, así que los modificadores, las fusiones y los estilos funcionan a partir de una sola cadena.
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> ); }
Los nombres que no se han importado en ninguna parte se cargan bajo demanda con una importación dinámica. webpack y esbuild la dividen en un pequeño chunk por icono y, hasta que llega ese chunk, Icon renderiza un SVG vacío del tamaño correcto, para que el diseño no dé saltos. Una compilación de producción de Vite deja esa importación intacta dentro de node_modules, por lo que, en ese caso, el nombre se queda vacío (la guía de tree shaking da los detalles). En todos los bundlers la solución es la misma: registra una vez, al arrancar, los datos de los nombres que renderizas a partir de cadenas, y se dibujan de forma síncrona, desde el primer renderizado y también en el servidor:
import { registerIcons } from 'glyphfox/react'; import { iconSettings, iconFile, iconCloud, iconLock } from 'glyphfox'; registerIcons([iconSettings, iconFile, iconCloud, iconLock]);
Las exportaciones de datos (iconSettings, iconArrowRight...) vienen del punto de entrada principal glyphfox y, como los componentes, son compatibles con tree shaking: importar una ocupa unos pocos cientos de bytes. Importar un componente como SettingsIcon también registra sus datos.
Modificadores y fusiones
Un modificador es una pequeña insignia en una esquina de cualquier icono: plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down o dot. El icono de debajo se recorta alrededor de la insignia dejando un hueco de recorte, así que las líneas nunca se tocan, sea cual sea el 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 iconos en un icono nuevo que sigue cumpliendo las reglas de los iconos: un único peso, la cuadrícula de 24 y el margen interior. Las disposiciones son overlap, side, stack, grid, orbit, badge e inside; gap define el hueco de recorte en unidades de la cuadrícula, y scale y offsets ajustan con precisión cada parte. Fusion acepta todas las props compartidas, así que un icono fusionado puede ser duotone, estar animado o llevar una etiqueta, como cualquier otro.
Morph y estados vivos
Tres herramientas se encargan del movimiento. MorphIcon se transforma cada vez que cambia su name. morphTo, en cualquier icono, lo transforma hacia un destino cuando se activa su trigger. animate reproduce un preset (draw, pop, wiggle, spin, pulse, bounce o shake) al montarse, al pasar el puntero por encima, al hacer clic o mientras active sea true.
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 un renderizador propio, useMorph(name, { duration }) devuelve los datos del icono en el fotograma actual, que puedes pasar a Icon mediante su prop icon o a tu propio código de dibujo. Todas las animaciones respetan prefers-reduced-motion. La guía de iconos animados repasa los presets, los disparadores y los pares de morph ajustados a mano.
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 y eventos
Los componentes se crean con forwardRef, así que una ref apunta al elemento <svg> renderizado. className se agrega después de las clases integradas glyphfox glyphfox-NAME, style se pasa tal cual, y cualquier otro atributo SVG o controlador de eventos (onClick, data-*, aria-*, id) va directamente al 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> ); }
Un aria-label pasado de esta forma también marca el icono como significativo: el componente cambia automáticamente de aria-hidden a role="img".
TypeScript
Los tipos vienen incluidos en el paquete. GlyphIconComponent es el tipo de todos los componentes de icono, GlyphProps son sus props (las props compartidas más todos los atributos SVG) y IconName, del punto de entrada principal, es la unión de todos los nombres de iconos, lo que te da autocompletado en Icon y en tus propios datos.
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" />; }
Importaciones y tamaño del bundle
Las importaciones con nombre de glyphfox/react son compatibles con tree shaking: cada icono es un módulo propio, creado con una llamada anotada como pura, y el paquete declara qué archivos tienen efectos secundarios. Las importaciones profundas como glyphfox/react/icons/home cargan directamente un único módulo de icono, lo que ayuda a las herramientas que no hacen tree shaking y evita que los servidores de desarrollo procesen el índice completo.
import { HomeIcon } from 'glyphfox/react/icons/home'; import FileIcon from 'glyphfox/react/icons/file'; // default export works too
La guía de tree shaking analiza, con mediciones, qué rompe el tree shaking, cuánto cuesta el runtime compartido y por qué la salida de la compilación contiene un chunk diminuto por icono.
Props
Todos los componentes de icono, Icon, Fusion y MorphIcon aceptan las mismas props. Tienen el mismo nombre y significado en Vue, Svelte, Angular, el web component y toSvg, así que un valor copiado del Estudio funciona en todas partes.
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
size | number, string | 24 | Ancho y alto; los números son píxeles. |
color | string | currentColor | Color principal. |
secondaryColor | string | color | Color de la capa duotone y del relleno sólido. |
secondaryOpacity | number | 0.3 / 1 | Opacidad de la capa duotone o del relleno sólido. |
weight | number | 2 | Trazo de 1 a 3 en la cuadrícula de 24, con compensación óptica por debajo de 24 px. |
absoluteWeight | boolean | false | Mantiene el trazo en weight píxeles a cualquier tamaño. |
corners | round, sharp | round | Uniones y extremos redondeados o rectos. |
variant | outline, duotone, solid | outline | Eje de estilo; solid se obtiene de las formas cerradas. |
rotate | number | 0 | Rotación en grados. |
flipX | boolean | false | Refleja en horizontal. |
flipY | boolean | false | Refleja en vertical. |
mirrorRtl | boolean | false | Refleja en layouts de derecha a izquierda. |
animate | draw, pop, wiggle, spin, pulse, bounce, shake | ninguno | Preset de estado vivo. |
trigger | mount, hover, click, state | mount | Cuándo se reproduce la animación o el morph. |
active | boolean | false | El estado para el disparador state. |
duration | number (ms) | según el preset | Duración de la animación o del morph. |
delay | number (ms) | 0 | Retraso de la animación o del morph. |
loop | boolean, number | false | Repite sin fin o un número de veces (spin y pulse se repiten por defecto). |
modifier | plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dot | ninguno | Insignia con hueco de recorte automático. |
modifierCorner | top-left, top-right, bottom-left, bottom-right | bottom-right | Esquina de la insignia. |
morphTo | name, data | ninguno | Destino del morph; el disparador decide cuándo se muestra. |
title | string | ninguno | Nombre accesible: title, role img y aria-label. |
decorative | boolean | true sin title | Oculta el icono a las tecnologías de apoyo. |
Icon y MorphIcon también aceptan name (cualquier forma de la sintaxis de nombres) o icon (datos de icono). Fusion acepta icons, layout, gap, scale y offsets.
Errores comunes
Iconse renderiza vacío al principio- Un nombre que todavía no está registrado se carga con una importación dinámica, así que el primer renderizado (y el renderizado en el servidor) es un SVG vacío. Importa el componente o llama a
registerIconscon los datos de cada nombre que renderices mediante una cadena. - Server Components de Next.js
- Los componentes usan hooks y el paquete no tiene la directiva
"use client", así que un Server Component no puede renderizarlos directamente. La guía de Next.js muestra la solución de un solo archivo y una opción sin JavaScript. - Colorear con
fill - Los iconos son trazos sobre
fill="none". Si pasasfill, se rellenan todas las formas, y eso rara vez es lo que quieres. Usacolor(o la propiedad CSScoloren un elemento padre) para el trazo yvariant="solid"para las formas rellenas. - El CSS global anula el peso
- Una regla de una hoja de estilos como
svg { stroke-width: 1.5 }tiene prioridad sobre el atributo SVG que lleva el eje de peso, incluida su compensación óptica. Limita el alcance de esas reglas o usa la propweight. - Los tamaños relativos se saltan la compensación óptica
- La compensación necesita conocer el tamaño en píxeles. Con
size="1em", el trazo se queda en el peso sin compensar, lo que puede verse fino con tamaños de texto pequeños; pasa un número de píxeles donde importe o unweightun poco más alto. - Llamar a
createIcondurante el renderizado createIcon(data)convierte tus propios datos de icono en un componente con todas las props. Llámalo una sola vez a nivel de módulo: si lo llamas dentro de un componente, crea un tipo de componente nuevo en cada renderizado y vuelve a montar el SVG.import *con una clave dinámicaIcons[name]sobre una importación de espacio de nombres mantiene todos los iconos en el bundle. Usa en su lugarIconcon un nombre, que solo carga lo que se renderiza.
Preguntas frecuentes
¿Puedo usar mis propios iconos con las mismas props?
Sí. createIcon(data) de glyphfox/react recibe datos de icono (name, body, tags, categories) y devuelve un componente con todas las props compartidas, incluidos el peso, los estilos duotone y solid, los modificadores y el morph. Dibuja el icono en el editor del Estudio o convierte un SVG existente con Fox-ify para que siga las mismas reglas de cuadrícula y trazo.
¿Cómo defino un tamaño o un peso predeterminado para todos los iconos?
El paquete de React no tiene proveedor, así que lo habitual es un pequeño componente envoltorio como const NavIcon = (props) => <Icon size={20} weight={1.75} {...props} />. El color no necesita nada: los iconos siguen el color CSS de su elemento padre.