Icônes dans SolidJS
Il n'existe pas encore de paquet dédié à Solid, et vous pouvez vous en passer. L'élément <glyph-fox> fonctionne dans les templates Solid, et un composant de quelques lignes basé sur glyphfox/core vous donne des icônes réactives, compatibles avec le tree shaking et rendues sur le serveur.
Installation
Installez le paquet principal. Tout ce qui figure sur cette page utilise des points d'entrée qu'il fournit : glyphfox/web pour l'élément, et glyphfox/core avec glyphfox/icons/NAME pour le composant.
npm install glyphfox
| Critère | Élément glyph-fox | Composant Glyph |
|---|---|---|
| Rendu | Dans le navigateur, lors de la mise à niveau de l'élément. | Sur le serveur et dans le navigateur. |
| Contenu livré | L'élément, son moteur et les icônes que vous enregistrez. | Le moteur de rendu et les modules d'icônes que vous importez. |
| Animation | Morphs à chaque changement de nom, déclencheurs de survol et de clic, états. | Animations CSS dans le SVG : presets et morphs au survol. |
| Idéal pour | Les icônes qui réagissent à l'utilisateur. | La plupart des icônes d'une application. |
L'élément glyph-fox
Enregistrez l'élément une seule fois, dans votre fichier d'entrée. glyphfox/web enregistre toutes les icônes ; pour limiter le bundle aux icônes que vous listez, utilisez glyphfox/web/element avec registerIcons, comme le montre le guide des web components.
import { render } from 'solid-js/web'; import 'glyphfox/web'; import App from './App'; render(() => <App />, document.getElementById('root'));
Les attributs statiques sont compilés dans le template : ils parviennent donc à l'élément sous forme d'attributs et fonctionnent tels quels :
export function Toolbar() { return ( <div class="toolbar"> <glyph-fox name="settings" size="20" weight="1.5" /> <glyph-fox name="bell" animate="shake" trigger="hover" /> </div> ); }
Les valeurs dynamiques, elles, se comportent autrement. Sur les éléments personnalisés, Solid assigne les expressions en tant que propriétés, or <glyph-fox> n'a pas de propriétés : il lit des attributs. Préfixez les props dynamiques avec l'espace de noms attr: pour que Solid définisse l'attribut à la place.
import { createSignal } from 'solid-js'; export function MenuButton() { const [open, setOpen] = createSignal(false); return ( <button type="button" aria-expanded={open()} aria-label={open() ? 'Close menu' : 'Open menu'} onClick={() => setOpen(!open())} > <glyph-fox attr:name={open() ? 'x' : 'menu'} morph duration="300" /> </button> ); }
Avec l'attribut morph, l'élément anime chaque changement de name : chaque basculement du signal joue donc le morph réglé à la main qui fait passer du menu à la fermeture. Les événements ne demandent rien de particulier : onClick sur un parent fonctionne comme d'habitude, et les déclencheurs comme trigger="click" sont gérés à l'intérieur de l'élément.
TypeScript
Les types JSX de Solid ne connaissent pas glyph-fox. Déclarez-le une fois dans un fichier de déclaration, et listez les attributs que vous définissez via attr: dans ExplicitAttributes, l'interface que Solid consulte pour cet espace de noms.
import 'solid-js'; type GlyphFoxAttributes = { name?: string; size?: string | number; color?: string; weight?: string | number; variant?: 'outline' | 'duotone' | 'solid'; animate?: 'draw' | 'pop' | 'wiggle' | 'spin' | 'pulse' | 'bounce' | 'shake'; trigger?: 'mount' | 'hover' | 'click' | 'state'; morph?: boolean | string; 'morph-to'?: string; duration?: string | number; }; declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'glyph-fox': JSX.HTMLAttributes<HTMLElement> & GlyphFoxAttributes; } interface ExplicitAttributes { name: string; size: string | number; active: boolean | string; } } }
Un petit composant Glyph
Pour les icônes qui n'ont pas besoin de l'interactivité intégrée à l'élément, rendez le SVG vous-même. renderToString de glyphfox/core convertit les données d'une icône en balisage avec toutes les props communes, et chaque module glyphfox/icons/NAME contient les données d'une seule icône : le bundle n'embarque donc que ce que vous importez.
import { splitProps } from 'solid-js'; import { renderToString } from 'glyphfox/core'; export function Glyph(props) { const [local, options] = splitProps(props, ['icon', 'class']); return ( <span class={local.class} style={{ display: 'inline-flex', 'line-height': '0' }} innerHTML={renderToString(local.icon, options)} /> ); }
import { Glyph } from './Glyph'; import home from 'glyphfox/icons/home'; import bell from 'glyphfox/icons/bell'; export function Nav(props) { return ( <nav> <a href="/"> <Glyph icon={home} size={20} /> Home </a> <button type="button" aria-label="Notifications"> <Glyph icon={bell} animate="shake" trigger="state" active={props.unread > 0} /> </button> </nav> ); }
L'effet qui met à jour innerHTML suit chaque prop lue par renderToString : si active, size ou icon change, le balisage est donc réécrit. Il est remplacé, et non interpolé. Pour un morph entre deux icônes, utilisez l'élément, ou un morph CSS au survol avec morphTo :
import { Glyph } from './Glyph'; import arrowRight from 'glyphfox/icons/arrow-right'; import chevronRight from 'glyphfox/icons/chevron-right'; export const NextLink = () => ( <a href="/next" class="next"> Next <Glyph icon={arrowRight} morphTo={chevronRight} trigger="hover" /> </a> );
Avec glyphfox/core, morphTo attend des données d'icône, pas un nom : seul toSvg, dans le point d'entrée principal, résout les noms. Un nom passé ici est ignoré et l'icône reste immobile. Le morph CSS se joue tant que le pointeur survole le svg ou son parent direct, qui est ici le span conteneur.
La syntaxe des noms (file+check@tr, cloud&lock) est elle aussi résolue par toSvg. Avec le core, utilisez plutôt les props et fonctions utilitaires correspondantes : modifier et modifierCorner pour les badges, fuse pour les fusions.
import { fuse } from 'glyphfox/core'; import { Glyph } from './Glyph'; import file from 'glyphfox/icons/file'; import cloud from 'glyphfox/icons/cloud'; import lock from 'glyphfox/icons/lock'; const secureCloud = fuse([cloud, lock], { layout: 'overlap' }); export const Status = () => ( <p> <Glyph icon={file} modifier="check" modifierCorner="top-right" title="Saved" /> <Glyph icon={secureCloud} size={32} title="Encrypted backup" /> </p> );
SolidStart et rendu côté serveur
Le composant Glyph est rendu sur le serveur comme n'importe quel autre balisage : SolidStart écrit le SVG dans le HTML, si bien que les icônes font partie du premier affichage et que la mise en page ne bouge pas lors de l'hydratation.
L'élément est une fonctionnalité du navigateur. Il est mis à niveau après l'exécution de son script et n'utilise pas le shadow DOM déclaratif : le HTML du serveur contient donc la balise vide. Réservez son emplacement avec CSS, ou gardez sur le composant Glyph les icônes qui doivent être visibles immédiatement. Les compromis propres à chaque framework sont présentés dans le guide sur le rendu côté serveur.
glyph-fox:not(:defined) { display: inline-block; width: 24px; height: 24px; }
Importer glyphfox/web sur le serveur est sans conséquence : l'élément vérifie la présence de customElements et ne fait rien en son absence. Importez-le tout de même depuis du code client, comme src/entry-client.tsx dans SolidStart, pour que l'élément et ses icônes restent hors du bundle serveur.
Props
Le composant Glyph transmet ses props à renderToString : il accepte donc les options communes, avec leurs noms en camelCase. Sur l'élément, ces mêmes props sont des attributs en kebab-case, listés dans le guide des web components.
| Option | 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. |
Pièges courants
- Props dynamiques sans attr:
name={...}surglyph-foxdéfinit une propriété que l'élément ignore, et l'icône s'affiche vide. Écrivezattr:name={...}. Les chaînes statiques fonctionnent sans le préfixe.- Un nom dans morphTo
renderToStringdu core attend des données d'icône pourmorphTo. Une chaîne est ignorée. Importez l'icône cible et passez ses données.- Les animations au montage se rejouent
- Chaque changement de prop remplace l'
innerHTML: un preset avec letrigger="mount"par défaut se rejoue donc. Pour les animations liées à un état, utiliseztrigger="state"avecactive. - Toutes les icônes embarquées par erreur
import { toSvg } from 'glyphfox'fait entrer toutes les icônes dans le bundle, car un nom peut désigner n'importe laquelle d'entre elles. Dans le code client, utilisez le core avec un module par icône ; réserveztoSvgau code exécuté uniquement sur le serveur.- L'élément sur le serveur
- Le HTML du serveur contient un
<glyph-fox>vide jusqu'à l'exécution du script. Réservez sa taille, ou rendez avec le composant Glyph les icônes qui doivent être visibles dès le rendu côté serveur. - Le span conteneur
- Le composant Glyph enveloppe le svg dans un span : les gaps de flex et de grid s'appliquent au span, et
classse retrouve sur le span, pas sur le svg. Définissez les tailles via les props plutôt qu'avec du CSS sur le span.
Questions fréquentes
Existe-t-il un paquet glyphfox pour Solid ?
Pas encore. Les deux approches de cette page utilisent ce que le paquet glyphfox fournit aujourd'hui : l'élément personnalisé, et le moteur de rendu du core sur lequel reposent les paquets React, Vue et Svelte.
Les icônes se mettent-elles à jour quand un signal change ?
Oui. Avec l'élément, liez les valeurs via attr: : l'élément se redessine à chaque changement d'attribut, avec un morph si l'attribut morph est présent. Avec le composant Glyph, l'effet qui met à jour innerHTML suit les props lues par le moteur de rendu et réécrit le balisage.