Icon
Ce qu'elle est. Un signe qui double un mot pour le rendre reconnaissable plus vite — dans un onglet, sur un bouton, en tête d'un bloc.
Ce qu'elle n'est pas. Ni un remplacement du mot — une icône seule n'est lisible que de qui la connaît déjà — ni une illustration : ce qui raconte est une image, et passe par <img>. Ni un bouton : une icône sur laquelle on clique est un Button qui porte une icône.
Composants Figma de la page Icons, 45:395.
ai-toolsarrow-narrow-downarrow-narrow-leftarrow-narrow-rightarrow-narrow-up-rightbookbook-openbox-pluscalendarcheckchevron-downchevron-leftchevron-rightchevron-topchurchcircle-face-contentcircle-infoclock-forwardclosecode-snippetcorner-right-downcrown-02disciplinesdocument-pedagogical-materialeditexpand-04file-plusfile-textfile-text-attachmentfile-text-sendfile-text-shieldfolder-checkglobe-3gridimage-plusinbox-1institutional-website-linkknowledge1knowledge2knowledge3link-2listluggage-1luggage-2mail-editmain-componentmenu-rightpassport-1pin-2pluspodcastpress-article-sourcequote-downroutesavesearch-2site-institutionnelstar-2sticky-notetelescopetimelinetrashusers-check
Le nom est celui du composant Figma, en minuscules et tirets. Il se vérifie à la compilation : icon="mail-edt" arrête le build, là où un chemin de fichier faux ne se voyait qu'en production, sur un 404.
Props
| Prop | Type | Défaut | Rôle |
|---|---|---|---|
name | IconName | — | Un des noms du registre. Un nom inconnu ne compile pas. |
size | 'sm' | 'md' | 'lg' | — | Les trois tokens button.icon-size.*. Absent : la taille vient du contexte. |
label | string | — | Nom accessible. Absent : l’icône est décorative et masquée. |
class | string | — | Classe supplémentaire pour la mise en page de l’appelant. |
Couleur
Une icône n'a pas de couleur à elle : les fichiers générés ne portent que currentColor. Elle prend donc celle du texte à côté duquel elle est posée, et suit son contexte sans qu'on ait à le lui dire. C'est le même fichier dans les trois cadres ci-dessous.
- Texte courant
- Texte secondaire
- Sur l'accent
C'est ce qui a fait disparaître arrow-right-on-accent.svg : le même dessin existait en double, une fois sombre pour les fonds clairs, une fois clair pour l'accent. Un <img> ne pouvait pas faire autrement. Les deux boutons ci-dessous montrent le même fichier.
Un composant peut nommer la teinte de ses icônes plutôt que de la laisser suivre le texte, par --icon-color. Button ne s'en sert que pour le primaire, où Figma lie l'icône à color/neutral/100 et le libellé à color/text/on-accent — quatre valeurs d'écart. Sur le secondaire, les deux sont la même encre : rien à nommer, currentColor suffit.
Au passage, une erreur trouvée par les icônes. Le libellé du bouton secondaire était écrit en --color-text-accent là où Figma dit color/text/default. Il fait 14 px : le seuil WCAG applicable est 4,5:1, et l'indigo tombait à 3,31:1 sur le fond d'appui — l'état pressé n'est pas exempté, contrairement à l'état désactivé. La description du token le disait déjà : « safe at body size (7.00:1 on the ground) », or le secondaire n'est pas sur le blanc mais sur la brume lavande. À l'encre, les trois états donnent 12,19:1, 9,50:1 et 6,47:1. L'écart préexistait ; il est devenu visible le jour où l'icône a cessé de porter sa couleur en dur.
Taille
Trois tailles, celles des tokens button.icon-size.*. Le glyphe est dessiné sur la grille 24 de Figma : à lg il est à l'échelle 1, en dessous il est réduit — jamais étiré.
smmdlg
Sans size, la taille vient du conteneur par la variable --icon-size. C'est ce que font Button et Nav, qui tiennent déjà leur taille d'icône de leur propre taille : l'icône s'accorde au bouton sans que l'appelant ait à la viser.
Tokens
--button-icon-size-sm — 20pxSmall button icon (20px). Above WCAG minimum for perceivable graphics.
--button-icon-size-md — 24pxMedium button icon (24px). Meets WCAG AAA for interactive graphic elements.
--button-icon-size-lg — 28pxLarge button icon (28px). Exceeds all guidelines for maximum visibility.
Écart à arbitrer côté Figma. Aucun token ne décrit la taille d'une icône en général : Icon emprunte button.icon-size.*, des variables qui décrivent le bouton. Tant qu'une icône ne vit qu'à l'intérieur d'un bouton ou d'un onglet, l'emprunt est exact ; il cessera de l'être à la première icône posée ailleurs. Une collection icon.size.* manque dans la source.
Accessibilité
Décorative par défaut. Sans label, l'icône est aria-hidden : elle double un mot déjà écrit à côté d'elle, et l'annoncer deux fois ne renseigne personne.
label quand elle est seule à porter le sens, et le texte dit alors l'action, pas le dessin : « Image suivante », pas « flèche droite ». Un bouton sans libellé — les flèches du carrousel — porte cette étiquette sur le bouton plutôt que sur l'icône : c'est le contrôle qu'on annonce, pas son décor.
Le cas de label lui-même est plus rare : une icône que rien n'accompagne, et dont l'absence retirerait une information. Le signe de citation ci-dessous en est un — il dit qu'on entre dans la parole de quelqu'un d'autre, et aucun mot alentour ne le dit à sa place.
Je ne savais pas que je pouvais changer d'avis en cours de route.
Ajouter une icône
La source est Figma, comme pour les tokens. Exporter le composant — pas le vecteur qu'il contient — dans icons/ sous son nom Figma, puis npm run icons. Le script vérifie la viewBox et le tracé, remplace les couleurs par currentColor, écrit le SVG nettoyé et la ligne du registre. L'icône apparaît alors ici, et son nom devient disponible partout.
On ne retouche pas un fichier de src/design-system/icons/ : il est régénéré. Une valeur qui paraît fausse se corrige dans Figma.
Correspondance avec Figma
| Nom dans le code | Composant Figma |
|---|---|
ai-tools | identique |
arrow-narrow-down | identique |
arrow-narrow-left | identique |
arrow-narrow-right | identique |
arrow-narrow-up-right | identique |
book | identique |
book-open | Book - Open |
box-plus | identique |
calendar | identique |
check | identique |
chevron-down | identique |
chevron-left | identique |
chevron-right | identique |
chevron-top | identique |
church | identique |
circle-face-content | Circle-face-content |
circle-info | identique |
clock-forward | identique |
close | identique |
code-snippet | identique |
corner-right-down | identique |
crown-02 | identique |
disciplines | identique |
document-pedagogical-material | identique |
edit | identique |
expand-04 | identique |
file-plus | identique |
file-text | File - Text |
file-text-attachment | identique |
file-text-send | identique |
file-text-shield | identique |
folder-check | identique |
globe-3 | identique |
grid | identique |
image-plus | identique |
inbox-1 | identique |
institutional-website-link | identique |
knowledge1 | identique |
knowledge2 | identique |
knowledge3 | identique |
link-2 | identique |
list | identique |
luggage-1 | identique |
luggage-2 | identique |
mail-edit | Mail-Edit |
main-component | identique |
menu-right | identique |
passport-1 | identique |
pin-2 | identique |
plus | identique |
podcast | identique |
press-article-source | identique |
quote-down | identique |
route | Route |
save | identique |
search-2 | identique |
site-institutionnel | identique |
star-2 | identique |
sticky-note | identique |
telescope | identique |
timeline | identique |
trash | identique |
users-check | identique |
Écart à arbitrer côté Figma. Le nommage de la page Icons mélange quatre conventions pour onze objets — File - Text, Circle-face-content, Mail-Edit, box-plus. Le code en hérite : d'où circle-face-content, qui dit une chose de trop. Renommer dans Figma ferait converger les deux noms, et le registre suivrait tout seul.
Écart à arbitrer côté Figma. Trois icônes — file-text, box-plus, mail-edit — s'exportent en aplat et non en tracé, parce que leur jointure de contour est mixte dans Figma. Leur tracé pèse alors dix à soixante fois celui des autres : 5 672 caractères pour mail-edit, contre 25 pour arrow-narrow-right. Uniformiser la jointure les ramènerait à un trait.
Le jeu complet vit sur Composants à travers les objets qui s'en servent : le Nav, le Button, le carrousel.