Raccourci clavier : Ctrl + K
Commencer

Iconographie

Vectis UI n'utilise ni n'embarque aucune police d'icônes (icon font). Les composants s'appuient exclusivement sur des tracés SVG en ligne (inline SVG), issus directement de la collection Material Symbols Rounded (poids 400, GRAD 0, taille optique 24px, sous licence Apache 2.0 © Google).

Vectis UI intègre 34 icônes distribuées dans des modules distincts pour garantir un tree-shaking parfait : seules les icônes réellement importées ou rendues dans votre application sont incluses dans le bundle final. Un composant comme VButton n'embarque ainsi aucune icône par défaut.
Chaque icône prend en charge la variante outline et, optionnellement, la version filled. Pour optimiser l'empreinte du code, le tracé filled n'est déclaré que si la propriété FILL modifie la géométrie de l'icône (ce qui concerne 15 des 34 icônes).

Les positions 3 et 4, ainsi que 6 et 7, illustrent un même symbole décliné successivement dans ses variantes 'outline' et 'filled'

Importer une icône

Les icônes fournies par la bibliothèque sont exportées sous forme de valeurs JavaScript depuis vectis-ui/icons. Elles se passent directement aux props dédiées aux icônes : une même référence d'icône s'utilise ainsi indifféremment sur le composant VIcon, un bouton, un champ de saisie ou un élément de menu.

ts
import { close, search } from 'vectis-ui/icons'
vue
<!-- one of the design system's own icons, imported above -->
<VIcon :name="close" />

<!-- every icon prop takes the same value -->
<VButton :icon-start="search">Search</VButton>

<!-- a bare NAME: your resolver, then the icon font as a ligature -->
<VIcon name="favorite" />

Passer une simple chaîne de caractères à une prop équivaut à fournir un nom d'icône : la valeur est alors transmise à votre résolveur d'icônes ou injectée sous forme de ligature pour une police d'icônes.
Les deux mécanismes (chaîne de caractères ou objet importé) ne répondent pas aux mêmes contraintes, et c'est cette distinction qui garantit le tree-shaking. Un tracé SVG n'est inclus dans le bundle final que parce qu'un module l'a importé de façon explicite, et non sur la base d'une chaîne évaluée dynamiquement à l'exécution..

Utiliser votre propre bibliothèque d'icônes

L'utilisation des icônes natives de Vectis UI est entièrement optionnelle. En configurant un résolveur d'icônes (une fonction chargée d'associer un nom à un composant ou un tracé SVG), celui-ci devient prioritaire sur les icônes par défaut. L'ensemble de vos composants adopte ainsi votre propre jeu d'icônes, garantissant une parfaite cohérence visuelle.
La bibliothèque inclut trois helpers (factories) adaptés aux différents formats du marché. Vous pouvez également définir votre propre résolveur sur mesure via une simple fonction de callback.

Configurez le résolveur à l'échelle globale de l'application (dans main.ts ou via un plugin Nuxt), et jamais au sein du setup() d'un composant ni de manière exclusive au client (client-only). Enregistrer le résolveur après la phase d'hydratation ou uniquement côté navigateur provoque un décalage (hydration mismatch), les icônes générées par le client ne correspondant plus au HTML initial envoyé par le serveur.

Quelle que soit la famille du résolveur, retourner undefined indique l'absence de correspondance pour un nom donné, et non une instruction d'omettre le rendu. Le composant déclenche alors son mécanisme de secours (fallback) : il utilise le tracé SVG natif du composant, puis retombe en dernier recours sur la ligature de la police d'icônes. Ce fonctionnement rend la cartographie partielle (partial mapping) parfaitement valide et recommandée : vous pouvez intercepter uniquement les noms d'icônes gérés par votre jeu personnalisé et déléguer le reste aux valeurs par défaut.

Lorsqu'un nom d'icône ne peut être résolu et qu'aucune police d'icônes n'est disponible, le composant affiche la chaîne de caractères brute, tronquée aux dimensions du conteneur de l'icône. Bien que la mise en page globale soit préservée, la présence d'un texte littéral à l'emplacement d'un symbole visuel constitue l'indicateur d'un échec de résolution.

Une police pilotée par classe

Pour les bibliothèques d'icônes basées sur des classes CSS (telles que Font Awesome, Phosphor ou Bootstrap Icons), l'affichage repose sur l'injection d'un glyphe via un pseudo-élément. La fonction className génère la classe CSS requise à partir de l'identifiant mappé et de la variante (filled ou outline). Le design system applique cette classe sur un élément <span> interne, ce qui permet de normaliser le dimensionnement et l'alignement de toutes les icônes au moyen d'une règle CSS unique.

ts
import { classIconResolver, setIconResolver } from 'vectis-ui'

// Font Awesome: the class names the icon, and the family carries the fill.
setIconResolver(
  classIconResolver({
    aliases: { close: 'xmark', search: 'magnifying-glass', expand_more: 'chevron-down' },
    className: (name, filled) => `${filled ? 'fa-solid' : 'fa-regular'} fa-${name}`,
  }),
)

L'option strict, activée par défaut, sécurise l'usage des correspondances partielles (partial mapping). Sans elle, un identifiant natif fourni par un composant mais absent de votre dictionnaire générerait une classe CSS inexistante pour la police d'icônes, entraînant un défaut d'affichage (rectangle vide). En s'abstenant de résoudre les identifiants non répertoriés, le mode strict autorise le tracé SVG natif à prendre le relais. Vos identifiants personnalisés restent traités normalement dès lors qu'ils figurent dans votre table de résolution.

Une police à ligatures

Pour les polices basées sur les ligatures (telles que Material Symbols ou une police IcoMoon configurée à cet effet), l'identifiant textuel de l'icône correspond directement au glyphe restitué. Ce résolveur accepte l'ensemble des noms transmis : la correspondance s'effectue directement au niveau de la table de ligatures de la police d'icônes. Ce mécanisme permet de substituer votre propre police aux tracés SVG natifs de Vectis UI sur l'intégralité du design system.

ts
import { ligatureIconResolver, setIconResolver } from 'vectis-ui'

// The name IS the glyph, so one line covers every icon in the application.
setIconResolver(ligatureIconResolver())

// Or, for a font spelling a few of them differently. The names left out
// are passed on as they stand.
setIconResolver(ligatureIconResolver({ aliases: { close: 'clear', more_horiz: 'more' } }))

Ce résolveur interceptant l'ensemble des requêtes, la table d'alias constitue la seule couche de correspondance : un nom présent dans la table est substitué, tandis qu'un nom absent est transmis inchangé à la police d'icônes. Ce mécanisme contourne la rétrogradation (fallback) vers les SVG natifs : tout nom non géré par la police se traduira par un glyphe manquant. Réservez ce résolveur aux projets dont la police d'icônes couvre la totalité des besoins applicatifs.

Un jeu de composants

Pour les bibliothèques distribuant leurs icônes sous forme de composants Vue (telles que Lucide ou Untitled UI), le rendu s'appuie directement sur les composants importés. Une contrainte d'architecture doit être respectée : chaque composant d'icône doit posséder un nœud <svg> unique à sa racine, indispensable à l'application du dimensionnement et du ciblage CSS par le design system. La fonction optionnelle props permet d'injecter des propriétés spécifiques lors du rendu (comme l'épaisseur de trait stroke-width ou une variante).

ts
import { componentIconResolver, setIconResolver } from 'vectis-ui'
import { Check, Search, X } from 'lucide-vue-next'

setIconResolver(
  componentIconResolver({
    // Three names answered here; every other one falls back to the built-in drawing.
    components: { check: Check, close: X, search: Search },
    props: () => ({ strokeWidth: 1.75 }),
  }),
)

Ce résolveur est strict par conception : lorsqu'un identifiant est absent de la table de correspondance, aucun composant ne peut être retourné. La résolution bascule alors sur la chaîne de fallback standard (tracé SVG natif, puis ligature). Mapper uniquement un jeu restreint d'icônes personnalisées et déléguer le reste aux valeurs par défaut du design system constitue un cas d'usage courant et parfaitement supporté.

Écrit à la main

Les trois fabriques intégrées ne couvrent pas nécessairement tous les cas d'usage. Un résolveur n'étant qu'une fonction associant un nom d'icône à un élément à rendre (composant, tracé SVG ou classe), écrire son propre résolveur constitue un modèle d'extension de premier ordre, et non une solution de dernier recours.
À titre d'exemple, voici le résolveur configuré pour ce site de documentation via un plugin Nuxt universel. Il traite les icônes propres à l'interface du site et retourne undefined pour tous les autres identifiants, déclenchant le fallback vers les tracés SVG natifs de Vectis UI.

ts
import { setIconResolver } from 'vectis-ui'

import { docsIcons } from '~/icons/icons'

// A resolver is only a function, so a table is not compulsory. This one is
// the site you are reading: the icons its chrome needs, and `undefined` for
// everything else, which hands the name back to the icon that carries it.
setIconResolver((name, context) => {
  const paths = docsIcons[name]
  if (!paths) return undefined
  return { path: (context.filled && paths[1]) || paths[0] }
})

Taille

Par défaut, une icône adopte une dimension de 1em, héritant automatiquement de la taille du texte environnant (font-size). Deux mécanismes permettent de surcharger ce comportement :

  • Surcharge locale : La prop size (en pixels), appliquée directement sur l'icône, prévaut sur toute autre règle stylistique.
  • Surcharge contextuelle : La variable CSS --vectis-icon-size, définie sur un élément ancêtre, se propage à toutes les icônes descendantes ne spécifiant pas leur propre prop size.

C'est cette seconde approche par cascade CSS qui permet aux composants de contrôle (via v-control) d'ajuster automatiquement la taille des icônes enfants selon la variante de taille du composant parent.

vue
<!-- 1em: the icon follows the text around it -->
<p>Ready <VIcon :name="check" /></p>

<!-- one icon, in pixels -->
<VIcon :name="check" :size="32" />

<!-- a context: every icon below is 20px unless it names its own -->
<div class="toolbar"><VIcon :name="check" /></div>

<style>
  .toolbar {
    --vectis-icon-size: 20px;
  }
</style>
La même icône à 16, 24 et 40 pixels.

Ordre de résolution

Le composant VIcon évalue sa source d'affichage selon un ordre de priorité immuable. Cet ordre de précédence constitue le contrat d'interface du composant :

  1. Prop render (fonction de rendu explicite)
  2. Prop src (valeur ou objet d'icône importé)
  3. Prop name (identifiant résolu séquentiellement : résolveur personnalisé -> tracé SVG natif embarqué -> ligature de la police d'icônes)
  4. Slot par défaut (contenu SVG ou HTML injecté)
vue
<!-- an explicit render wins over everything else -->
<VIcon :render="{ src: '/logo.svg' }" label="Logo" />

<!-- an imported icon: your resolver is asked first, its own drawing answers next -->
<VIcon :name="close" />

<!-- a bare name: your resolver, then the ligature font -->
<VIcon name="favorite" />

<!-- nothing named at all: the slot is drawn -->
<VIcon><svg viewBox="0 0 24 24"><path d="…" /></svg></VIcon>

Une chaîne de caractères est systématiquement traitée comme un nom d'icône. Pour déclarer une image, un composant ou un style spécifique, la valeur doit être passée explicitement sous forme d'objet ({ src }, { component }, { path }, { text } ou { class }). L'absence totale d'heuristique garantit qu'un identifiant à espace de noms tel que mdi:close (format Iconify) parvienne intact à votre résolveur sans risque d'être interprété à tort comme une URL ou un chemin réseau.

Icônes existantes

Vectis UI intègre un jeu de 34 icônes natives. Leurs identifiants constituent le vocabulaire de référence pour établir vos tables d'alias. Vous pouvez importer directement les icônes nécessaires depuis le sous-module vectis-ui/icons pour un rendu explicite, ou mapper leurs identifiants au sein de votre résolveur afin de substituer l'iconographie par défaut par votre propre système visuel.

Lorsque deux variantes de glyphes coexistent, la propriété filled bascule l'affichage du style filaire au style plein. Pour les icônes constituées d'un tracé unique, le contour représente l'intégralité du motif : la propriété filled n'a alors aucun effet sur le rendu visuel.

  • arrow_downward
  • arrow_downward_alt
  • arrow_drop_down
  • arrow_drop_up
  • arrow_left_alt
  • arrow_right_alt
  • arrow_upward
  • arrow_upward_alt
  • attach_file
  • audio_file
  • calendar_today
  • check
  • check_circle
  • chevron_left
  • chevron_right
  • close
  • cloud_upload
  • code
  • description
  • error
  • expand_less
  • expand_more
  • folder_zip
  • image
  • info
  • more_horiz
  • notifications
  • picture_as_pdf
  • schedule
  • search
  • swap_vert
  • table_chart
  • video_file
  • warning