Icônes Angular
glyphfox-angular ajoute un composant standalone gf-icon et un provider qui enregistre les icônes par nom. Il prend en charge Angular 17 et les versions ultérieures, le rendu côté serveur ainsi que la détection de changements OnPush et zoneless.
Installation
npm install glyphfox glyphfox-angular
glyphfox-angular est publié au format de package Angular, construit avec ng-packagr, et s'appuie sur glyphfox pour les données d'icônes et le moteur de rendu. Sa dépendance peer est @angular/core 17 ou plus récent, car les inputs reposent sur des transformations d'input comme booleanAttribute.
Enregistrer les icônes avec provideGlyphFox
gf-icon recherche les icônes par leur nom : enregistrez donc celles qu'utilisent vos templates. Chaque icône est un export de données nommé de glyphfox : home correspond à iconHome, arrow-right à iconArrowRight.
import { ApplicationConfig } from '@angular/core'; import { provideRouter } from '@angular/router'; import { iconCheck, iconFile, iconHome, iconMenu, iconSave, iconSearch, iconX } from 'glyphfox'; import { provideGlyphFox } from 'glyphfox-angular'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideGlyphFox({ icons: [iconHome, iconSearch, iconFile, iconMenu, iconX, iconSave, iconCheck], defaults: { weight: 1.75 }, }), ], };
defaults s'applique à chaque gf-icon placé sous cet injecteur, et un input défini sur l'élément l'emporte sur la valeur par défaut. Plusieurs appels à provideGlyphFox dans le même injecteur se cumulent : toutes leurs icônes sont enregistrées et leurs valeurs par défaut sont combinées dans l'ordre. provideGlyphFoxIcons(icons) est la forme courte quand vous enregistrez uniquement des icônes.
Pour rendre toutes les icônes disponibles par nom, passez l'objet complet : import { icons } from 'glyphfox' puis provideGlyphFox({ icons }). Les données des 419 icônes se retrouvent alors dans le bundle qui charge le provider, soit environ 105 Ko minifiés et 25 Ko après gzip : réservez donc cette option aux prototypes et aux outils internes. Deux exports de données nommés coûtent bien moins de 1 Ko.
Utiliser gf-icon
import { Component, signal } from '@angular/core'; import { GlyphFoxIcon } from 'glyphfox-angular'; @Component({ selector: 'app-toolbar', standalone: true, // the default from Angular 19 imports: [GlyphFoxIcon], template: ` <a href="/" aria-label="Home"><gf-icon name="home" /></a> <gf-icon name="search" size="20" /> <gf-icon name="file+check@tr" variant="duotone" secondaryColor="#ff7a1a" /> <button type="button" aria-label="Menu" [attr.aria-expanded]="open()" (click)="open.set(!open())"> <gf-icon name="menu" morphTo="x" trigger="state" [active]="open()" /> </button> `, }) export class Toolbar { readonly open = signal(false); }
Les inputs reprennent les noms de props en camelCase : secondaryColor, modifierCorner, flipX. Les chaînes statiques fonctionnent pour tous les inputs, y compris numériques (size="20" devient le nombre 20), et les inputs booléens acceptent un attribut sans valeur : <gf-icon name="arrow-right" mirrorRtl /> inverse ainsi la flèche dans les mises en page de droite à gauche.
class et style s'appliquent à l'hôte gf-icon, une boîte inline flex autour du svg. Les traits utilisent currentColor : la propriété CSS color de l'hôte ou de n'importe quel parent colore donc l'icône, et l'input color la définit directement.
Modificateurs, styles et fusion
name accepte la syntaxe de nom complète. file+check ajoute un badge, @tl, @tr, @bl ou @br choisit son coin, et heart/solid choisit un style. Les badges sont dessinés par le moteur : seule l'icône de base doit donc être enregistrée. Pour une fusion, passez les parties à [icons] et choisissez une disposition avec layout.
<gf-icon name="cloud+sync@tr" /> <gf-icon name="heart/solid" color="#e5484d" /> <gf-icon [icons]="['cloud', 'lock']" layout="overlap" [gap]="1" /> <gf-icon [icons]="['user', 'shield']" layout="badge" /> <gf-icon [icons]="['file', 'image', 'music', 'video']" layout="grid" />
Une fusion est résolue par nom comme toute autre icône : chaque partie doit donc être enregistrée. Le résultat suit weight, variant et les autres inputs, et là où les parties se chevauchent, celle de derrière est découpée autour de celle de devant. Les dispositions sont overlap, side, stack, grid, orbit, badge et inside.
Données d'icône au lieu des noms
L'input icon accepte directement des données d'icône et contourne le registre, ce qui convient aux icônes choisies dans le code à partir d'une table fixe.
import { Component, computed, input } from '@angular/core'; import { iconFile, iconFileCode, iconFileImage, iconFileText } from 'glyphfox'; import { GlyphFoxIcon } from 'glyphfox-angular'; const byType = { code: iconFileCode, image: iconFileImage, text: iconFileText }; type FileType = keyof typeof byType; @Component({ selector: 'app-file-row', standalone: true, imports: [GlyphFoxIcon], template: `<gf-icon [icon]="icon()" size="18" /> {{ name() }}`, }) export class FileRow { readonly name = input.required<string>(); readonly type = input<FileType | null>(null); readonly icon = computed(() => { const type = this.type(); return type ? byType[type] : iconFile; }); }
Icônes des routes en lazy loading
provideGlyphFox renvoie des environment providers : la fonction s'utilise donc aussi dans les providers d'une route. Déclarées dans un fichier de routes chargé en lazy loading, les icônes d'une fonctionnalité voyagent avec le chunk lazy plutôt qu'avec le bundle principal.
import { iconHome, iconMenu, iconSearch, iconX } from 'glyphfox'; import type { GlyphFoxConfig } from 'glyphfox-angular'; export const sharedIcons = { icons: [iconHome, iconSearch, iconMenu, iconX], defaults: { weight: 1.75 }, } satisfies GlyphFoxConfig;
import { Routes } from '@angular/router'; export const routes: Routes = [ { path: 'billing', loadChildren: () => import('./billing/billing.routes').then((m) => m.BILLING_ROUTES) }, ];
import { Routes } from '@angular/router'; import { iconCreditCard, iconReceipt, iconWallet } from 'glyphfox'; import { provideGlyphFox } from 'glyphfox-angular'; import { sharedIcons } from '../icons'; import { BillingPage } from './billing.page'; export const BILLING_ROUTES: Routes = [ { path: '', providers: [ provideGlyphFox({ ...sharedIcons, icons: [...sharedIcons.icons, iconCreditCard, iconReceipt, iconWallet] }), ], component: BillingPage, }, ];
Une route qui appelle provideGlyphFox obtient sa propre configuration. Angular ne combine pas les multi providers d'un injecteur à l'autre : les composants situés sous cette route ne lisent donc que l'appel de la route, valeurs par défaut comprises. Décomposer un objet partagé (spread), comme ci-dessus, conserve les icônes et les valeurs par défaut de la racine.
Rendu côté serveur et hydratation
gf-icon écrit son svg via Renderer2 : avec Angular SSR ou le prérendu, l'icône figure donc déjà dans le HTML, et le navigateur redessine le même balisage à l'initialisation du composant. Le serveur ne dispose pas de requestAnimationFrame : un morph y passe directement à sa valeur finale, et un morph avec le déclencheur par défaut (mount) ne se joue qu'une fois l'application démarrée dans le navigateur.
Enregistrez chaque icône rendue par le serveur. Un nom non enregistré est récupéré via un import dynamique, et cette requête peut être encore en cours quand le serveur sérialise la page, ce qui laisse une icône vide dans le HTML jusqu'à ce que l'hydratation la remplisse.
Ce même chargeur explique un détail des builds de production : la sortie liste un petit chunk par icône, car le builder intègre au bundle chaque cible possible de cet import dynamique. Ces chunks ne sont téléchargés que pour les noms que vous n'avez pas enregistrés.
OnPush, signaux et applications zoneless
gf-icon utilise OnPush et dessine lui-même son svg chaque fois qu'un input change, lors des déclencheurs de survol et de clic, et à chaque image d'un morph. Il ne dépend pas de zone.js et fonctionne donc dans les applications zoneless ; les signaux se lient comme n'importe quelle autre valeur : [active]="saved()".
import { Component, signal } from '@angular/core'; import { GlyphFoxIcon } from 'glyphfox-angular'; @Component({ selector: 'app-save-button', standalone: true, imports: [GlyphFoxIcon], template: ` <button type="button" (click)="save()"> <gf-icon name="save" morphTo="check" trigger="state" [active]="saved()" [duration]="300" /> {{ saved() ? 'Saved' : 'Save' }} </button> `, }) export class SaveButton { readonly saved = signal(false); save() { this.saved.set(true); setTimeout(() => this.saved.set(false), 1500); } }
Les préréglages d'états vivants fonctionnent de la même façon : <gf-icon name="bell" animate="shake" trigger="state" [active]="hasNews()" /> fait osciller la cloche tant que le signal est vrai, et animate="spin" sur loader-circle en fait un indicateur de chargement. Les animations sont du CSS intégré au svg et s'arrêtent en mode mouvement réduit ; le guide des icônes animées liste tous les préréglages et déclencheurs.
Inputs
Chaque prop commune est un input qui porte le même nom et a le même sens que dans les autres packages glyphfox.
| Input | 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. |
En plus des props communes, gf-icon accepte name (toute spécification), icon (données d'icône), icons (de 2 à 10 parties d'une fusion), layout et gap.
Pièges courants
- provideGlyphFox dans un composant
- Cette fonction renvoie des environment providers, dont la place est dans la configuration de l'application, dans un NgModule ou dans une route. Angular les refuse dans les
providersd'un composant. - Une route lazy perd les valeurs par défaut de la racine
- Les providers d'une route remplacent la configuration de tout ce qui se trouve sous cette route, car les multi providers ne sont pas combinés d'un injecteur à l'autre. Décomposez (spread) un objet de configuration partagé dans chaque appel.
- aria-label sur l'hôte
- Un
aria-labelsurgf-iconrend le svg interne non décoratif (role="img"), mais le libellé reste sur l'élément hôte, qui n'a pas de rôle : les lecteurs d'écran risquent donc de ne rien annoncer. Utilisez l'inputtitlepour une icône porteuse de sens, ou donnez un libellé au bouton parent et gardez l'icône décorative. - Une fusion qui n'apparaît jamais
- Si une partie de
[icons]n'est pas enregistrée, toute la fusion l'attend et reste vide entre-temps, y compris côté serveur. Enregistrez chaque partie. - Enregistrer tout le jeu d'icônes par mégarde
provideGlyphFox({ icons })avec l'objet complet deglyphfoxconserve toutes les icônes dans le bundle. Importez plutôt les exports de données nommés dont vous avez besoin.
Questions fréquentes
Puis-je utiliser glyphfox-angular dans une application basée sur les NgModule ?
Oui. GlyphFoxIcon est un composant standalone : ajoutez-le aux imports du NgModule qui déclare vos composants, et placez provideGlyphFox(...) dans les providers de votre module racine.
Quelles versions d'Angular sont prises en charge ?
Angular 17 et les versions ultérieures, soit la plage de la dépendance peer du package. En 17 et 18, conservez standalone: true sur les composants qui importent GlyphFoxIcon ; à partir de la 19, c'est la valeur par défaut. Les balises auto-fermantes comme <gf-icon name="home" /> fonctionnent dans toutes les versions prises en charge.