Icônes React
Chaque icône glyphfox est un composant React qui génère du SVG inline. Les mêmes props fonctionnent sur toutes les icônes, aucun provider n'est nécessaire, et les composants que vous n'importez pas ne se retrouvent jamais dans votre bundle.
Installation
Les composants React se trouvent dans le package principal glyphfox, sous le point d'entrée glyphfox/react. React est une dépendance peer optionnelle : le package fonctionne avec React 16.8 et les versions ultérieures, car il n'a besoin que des hooks et de forwardRef, et sa suite de tests s'exécute sur React 19.
npm install glyphfox
Il n'y a aucune feuille de style à importer ni aucun plugin de build à ajouter. Le package fournit des builds ESM et CommonJS accompagnés de déclarations de types : Vite, webpack, Rspack, esbuild et Parcel le prennent donc en charge tel quel.
Afficher vos premières icônes
Chaque icône est exportée sous son nom en PascalCase, suivi du suffixe Icon : home devient HomeIcon, arrow-right devient ArrowRightIcon et message-circle devient MessageCircleIcon. Cherchez un nom dans l'explorateur d'icônes ; la page de chaque icône, comme arrow right, affiche aussi la ligne d'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> ); }
Sans props, une icône mesure 24 pixels sur 24, se dessine avec stroke="currentColor" pour reprendre la couleur du texte de son parent, et porte aria-hidden="true", car la plupart des icônes accompagnent un libellé visible. Donnez-lui un title quand l'icône est seule à porter le sens ; le guide d'accessibilité présente les modèles à suivre.
Taille, couleur, épaisseur et style
Chaque icône se décline selon trois axes : l'épaisseur, les coins et le style. Ce sont de simples props : elles peuvent donc suivre l'état, les thèmes ou les points de rupture comme n'importe quelle autre valeur.
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 /> </> ); }
sizeaccepte un nombre de pixels ou toute longueur CSS sous forme de chaîne, comme"1.25em".weightva de 1 à 3 sur la grille de 24. Sous 24 pixels, le trait bénéficie d'une compensation optique et devient jusqu'à 30 % plus épais aux plus petites tailles, si bien qu'une icône de 16 pixels garde la même présence qu'une icône de 24 pixels.absoluteWeightdésactive cette compensation et maintient le trait à exactementweightpixels.variant="duotone"utilise la seconde couche dessinée à la main quand l'icône en possède une, ou, à défaut, un remplissage translucide de ses formes fermées.variant="solid"remplit les formes fermées et évide les lignes intérieures, qui deviennent de l'espace négatif.mirrorRtlretourne horizontalement les icônes directionnelles lorsqu'elles s'affichent dans un contextedir="rtl": le même balisage fonctionne ainsi dans les deux sens.
Icônes par nom
Quand l'icône provient de données, d'un champ de CMS, d'une table de routes ou d'un réglage utilisateur, affichez-la avec Icon et un nom. La prop name accepte la syntaxe de nom complète, commune à tous les packages glyphfox : modificateurs, fusions et styles tiennent donc dans une seule chaîne.
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> ); }
Les noms qui ne sont importés nulle part sont chargés à la demande via un import dynamique. webpack et esbuild découpent cet import en un petit chunk par icône, et tant que ce chunk n'est pas arrivé, Icon affiche un SVG vide aux bonnes dimensions, pour que la mise en page ne saute pas. Un build de production Vite laisse cet import tel quel dans node_modules : l'icône y reste donc vide (le guide du tree shaking donne les détails). Quel que soit le bundler, la solution est la même : enregistrez une fois au démarrage les données des noms que vous affichez à partir de chaînes, et leur rendu devient synchrone, dès le premier affichage comme côté serveur :
import { registerIcons } from 'glyphfox/react'; import { iconSettings, iconFile, iconCloud, iconLock } from 'glyphfox'; registerIcons([iconSettings, iconFile, iconCloud, iconLock]);
Les exports de données (iconSettings, iconArrowRight...) proviennent du point d'entrée principal glyphfox et profitent du tree shaking comme les composants : en importer un ne coûte que quelques centaines d'octets. Importer un composant comme SettingsIcon enregistre également ses données.
Modificateurs et fusions
Un modificateur est un petit badge placé dans un coin de n'importe quelle icône : plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down ou dot. L'icône sous-jacente est évidée autour du badge grâce à un espace de découpe, si bien que les lignes ne se touchent jamais, quelle que soit l'épaisseur.
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 combine de 2 à 10 icônes en une nouvelle icône qui respecte toujours les règles communes à toutes les icônes : une seule épaisseur, la grille de 24 et la zone de padding. Les dispositions sont overlap, side, stack, grid, orbit, badge et inside ; gap définit l'espace de découpe en unités de grille, tandis que scale et offsets ajustent finement chaque partie. Fusion accepte toutes les props communes : une icône fusionnée peut donc être duotone, animée ou dotée d'un libellé, comme n'importe quelle autre.
Morph et états vivants
Trois outils prennent en charge l'animation. MorphIcon se transforme chaque fois que sa prop name change. Sur n'importe quelle icône, morphTo la fait se transformer vers une cible quand son trigger se déclenche. animate joue un préréglage (draw, pop, wiggle, spin, pulse, bounce ou shake) au montage, au survol, au clic ou tant que active est vrai.
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'} /> </> ); }
Pour un rendu personnalisé, useMorph(name, { duration }) renvoie les données d'icône de l'image d'animation en cours, que vous pouvez passer à Icon via sa prop icon ou à votre propre code de dessin. Toutes les animations respectent prefers-reduced-motion. Le guide des icônes animées détaille les préréglages, les déclencheurs et les paires de morph ajustées à la main.
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 et événements
Les composants sont des composants forwardRef : une ref pointe donc vers l'élément <svg> rendu. className s'ajoute après les classes intégrées glyphfox glyphfox-NAME, style est transmis tel quel, et tous les autres attributs SVG ou gestionnaires d'événements (onClick, data-*, aria-*, id) vont directement sur l'élément.
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 transmis de cette façon signale aussi l'icône comme porteuse de sens : le composant remplace automatiquement aria-hidden par role="img".
TypeScript
Les types sont fournis avec le package. GlyphIconComponent est le type de chaque composant d'icône, GlyphProps décrit ses props (les props communes plus tous les attributs SVG), et IconName, exporté par le point d'entrée principal, est l'union de tous les noms d'icônes, ce qui vous offre l'autocomplétion sur Icon et dans vos propres données.
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 et taille du bundle
Les imports nommés depuis glyphfox/react profitent du tree shaking : chaque icône est un module distinct, créé avec une annotation pure, et le package déclare quels fichiers ont des effets de bord. Les imports profonds comme glyphfox/react/icons/home chargent directement un seul module d'icône, ce qui aide les outils dépourvus de tree shaking et évite aux serveurs de développement de traiter l'index complet.
import { HomeIcon } from 'glyphfox/react/icons/home'; import FileIcon from 'glyphfox/react/icons/file'; // default export works too
Ce qui casse le tree shaking, ce que coûte le runtime partagé et pourquoi le build contient un minuscule chunk par icône : tout cela est mesuré dans le guide du tree shaking.
Props
Tous les composants d'icônes, ainsi que Icon, Fusion et MorphIcon, acceptent les mêmes props. Elles portent le même nom et ont le même sens dans Vue, Svelte, Angular, le web component et toSvg : une valeur copiée depuis le Studio fonctionne donc partout.
| Prop | Type | Par défaut | Description |
|---|---|---|---|
size | number, string | 24 | Largeur et hauteur ; les nombres sont en pixels. |
color | string | currentColor | Couleur principale. |
secondaryColor | string | color | Couleur du calque duotone et du remplissage plein. |
secondaryOpacity | number | 0.3 / 1 | Opacité du calque duotone ou du remplissage plein. |
weight | number | 2 | Trait de 1 à 3 sur la grille de 24, avec compensation optique en dessous de 24 px. |
absoluteWeight | boolean | false | Garde le trait à weight pixels quelle que soit la taille. |
corners | round, sharp | round | Jointures et extrémités arrondies ou vives. |
variant | outline, duotone, solid | outline | Axe de style ; solid vient des formes fermées. |
rotate | number | 0 | Rotation en degrés. |
flipX | boolean | false | Miroir horizontal. |
flipY | boolean | false | Miroir vertical. |
mirrorRtl | boolean | false | Miroir dans les mises en page de droite à gauche. |
animate | draw, pop, wiggle, spin, pulse, bounce, shake | aucun | Préréglage d'état vivant. |
trigger | mount, hover, click, state | mount | Moment où l'animation ou le morph se joue. |
active | boolean | false | L'état pour le déclencheur state. |
duration | number (ms) | selon le préréglage | Durée de l'animation ou du morph. |
delay | number (ms) | 0 | Délai de l'animation ou du morph. |
loop | boolean, number | false | Répète à l'infini ou un certain nombre de fois (spin et pulse bouclent par défaut). |
modifier | plus, minus, check, x, alert, lock, clock, sync, arrow-up, arrow-down, dot | aucun | Badge avec espace de découpe automatique. |
modifierCorner | top-left, top-right, bottom-left, bottom-right | bottom-right | Coin du badge. |
morphTo | name, data | aucun | Cible du morph ; le déclencheur décide quand elle s'affiche. |
title | string | aucun | Nom accessible : title, role img et aria-label. |
decorative | boolean | true sans title | Masque l'icône aux technologies d'assistance. |
Icon et MorphIcon acceptent aussi name (toute syntaxe de nom) ou icon (données d'icône). Fusion accepte icons, layout, gap, scale et offsets.
Pièges courants
Icons'affiche d'abord vide- Un nom qui n'est pas encore enregistré est récupéré via un import dynamique : le premier rendu (et le rendu côté serveur) produit donc un SVG vide. Importez le composant, ou appelez
registerIconsavec les données de chaque nom que vous affichez à partir d'une chaîne. - Server Components de Next.js
- Les composants utilisent des hooks et le package ne comporte pas de directive
"use client": un Server Component ne peut donc pas les afficher directement. Le guide Next.js présente la correction en un seul fichier ainsi qu'une option sans aucun JavaScript. - Colorer avec
fill - Les icônes sont des traits sur
fill="none". Passerfillremplit toutes les formes, ce qui est rarement l'effet voulu. Utilisezcolor(ou la propriété CSScolorsur un parent) pour le trait etvariant="solid"pour des formes pleines. - Du CSS global écrase l'épaisseur
- Une règle de feuille de style comme
svg { stroke-width: 1.5 }l'emporte sur l'attribut SVG qui porte l'axe d'épaisseur, compensation optique comprise. Limitez la portée de ces règles ou utilisez la propweight. - Pas de compensation optique avec les tailles relatives
- La compensation doit connaître la taille en pixels. Avec
size="1em", le trait reste à l'épaisseur nominale, ce qui peut paraître trop fin avec de petites tailles de texte ; passez un nombre de pixels là où c'est important, ou une valeur deweightlégèrement plus élevée. - Appeler
createIconpendant le rendu createIcon(data)transforme vos propres données d'icône en un composant doté de toutes les props. Appelez-la une seule fois au niveau du module : l'appeler dans un composant crée un nouveau type de composant à chaque rendu et remonte le SVG.import *avec une clé dynamiqueIcons[name]sur un import d'espace de noms conserve toutes les icônes dans le bundle. Utilisez plutôtIconavec un nom, qui ne charge que ce qui est affiché.
Questions fréquentes
Puis-je utiliser mes propres icônes avec les mêmes props ?
Oui. createIcon(data), exportée par glyphfox/react, prend des données d'icône (name, body, tags, categories) et renvoie un composant doté de toutes les props communes, y compris l'épaisseur, les styles duotone et solid, les modificateurs et le morph. Dessinez l'icône dans l'éditeur du Studio ou convertissez un SVG existant avec Fox-ify, pour que l'icône respecte les mêmes règles de grille et de trait.
Comment définir une taille ou une épaisseur par défaut pour toutes les icônes ?
Le package React n'a pas de provider : la méthode habituelle consiste donc à écrire un petit wrapper comme const NavIcon = (props) => <Icon size={20} weight={1.75} {...props} />. La couleur ne demande rien : les icônes suivent la propriété CSS color de leur parent.