Raccourci clavier : Ctrl + K
Commencer

Icône

Une icône, depuis la source dont vous disposez. La bibliothèque embarque ses propres dessins, donc rien ici n'exige de police d'icônes, et un résolveur permet de brancher un jeu tiers à la place.

Utilisation

vue
<script setup lang="ts">
import { VIcon } from 'vectis-ui'
import { search } from 'vectis-ui/icons'
</script>

<template>
  <VIcon :name="search" label="Search" />
</template>

Exemples

Taille

size est un nombre de pixels, l'icône étant carrée. Sans elle, l'icône prend la taille que son contexte impose, et retombe sur 1em en l'absence de contexte.

vue

16

20

24

32

48

Small text, with a in it.

Larger text, with a in it.

A heading

<script setup lang="ts">
import { VButton, VIcon, VTypography } from 'vectis-ui'
import { notifications } from 'vectis-ui/icons'

const SIZES = [16, 20, 24, 32, 48]
</script>

<template>
  <div class="stack">
    <div class="row">
      <div v-for="size in SIZES" :key="size" class="cell">
        <VIcon :name="notifications" :size="size" />
        <VTypography variant="caption" tone="muted">{{ size }}</VTypography>
      </div>
    </div>

    <!-- Given no size, the icon takes the one its context imposes: a control sets one
         for everything drawn inside it, so these three need nothing of their own. -->
    <div class="row">
      <VButton :icon-start="notifications" size="sm">Small</VButton>
      <VButton :icon-start="notifications">Medium</VButton>
      <VButton :icon-start="notifications" size="lg">Large</VButton>
    </div>

    <!-- And with no context either, it falls back to 1em and follows the text it sits in. -->
    <div class="prose">
      <VTypography variant="body-sm">
        Small text, with a <VIcon :name="notifications" /> in it.
      </VTypography>
      <VTypography variant="body-lg">
        Larger text, with a <VIcon :name="notifications" /> in it.
      </VTypography>
      <VTypography variant="heading-2">A heading <VIcon :name="notifications" /></VTypography>
    </div>
  </div>
</template>

<style scoped>
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--vectis-space-7);
}
.row {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--vectis-space-5);
}
.cell {
  display: grid;
  justify-items: center;
  gap: var(--vectis-space-2);
}
.prose {
  display: grid;
  gap: var(--vectis-space-2);
}
</style>

Pleine

filled demande la forme pleine de l'icône, ce qui sert à marquer un état. Une icône de la bibliothèque sans dessin plein rend celui qu'elle a toujours eu.

vue

notifications

check_circle

warning

error

info

schedule

search, unchanged by filling

<script setup lang="ts">
import { VIcon, VTypography } from 'vectis-ui'
import {
  check_circle as checkCircle,
  error,
  info,
  notifications,
  schedule,
  search,
  warning,
} from 'vectis-ui/icons'

/* Six of the icons whose geometry really changes when they are filled. */
const PAIRS = [notifications, checkCircle, warning, error, info, schedule]
</script>

<template>
  <div class="stack">
    <div class="row">
      <div v-for="icon in PAIRS" :key="icon.name" class="cell">
        <span class="pair">
          <VIcon :name="icon" :size="28" />
          <VIcon :name="icon" :size="28" filled />
        </span>
        <VTypography variant="caption" tone="muted">{{ icon.name }}</VTypography>
      </div>
    </div>

    <!-- An icon whose geometry filling does not change is drawn as it always was. The
         prop is inert rather than wrong, so it can be bound without checking first. -->
    <div class="cell start">
      <span class="pair">
        <VIcon :name="search" :size="28" />
        <VIcon :name="search" :size="28" filled />
      </span>
      <VTypography variant="caption" tone="muted">search, unchanged by filling</VTypography>
    </div>
  </div>
</template>

<style scoped>
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--vectis-space-6);
}
.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vectis-space-6);
}
.cell {
  display: grid;
  justify-items: center;
  gap: var(--vectis-space-2);
}
.start {
  justify-items: start;
}
.pair {
  display: inline-flex;
  gap: var(--vectis-space-3);
}
</style>

En miroir

mirrored retourne l'icône dans un contexte de droite à gauche, pour un glyphe qui désigne une direction physique : un chevron « précédent » pointe à gauche en français et à droite en arabe. La direction est celle que le navigateur a calculée, donc un dir sur n'importe quel ancêtre suffit. La plupart des icônes disent la même chose dans les deux sens et ne se retournent pas.

vue

ltr

rtl

<script setup lang="ts">
import { VIcon, VTypography } from 'vectis-ui'
import { arrow_right_alt as arrowRight, chevron_left as chevronLeft, search } from 'vectis-ui/icons'
</script>

<template>
  <div class="stack">
    <div v-for="dir in ['ltr', 'rtl']" :key="dir" :dir="dir" class="row">
      <VTypography variant="caption" tone="muted">{{ dir }}</VTypography>
      <VIcon :name="chevronLeft" :size="28" mirrored />
      <VIcon :name="arrowRight" :size="28" mirrored />
      <!-- A magnifier means the same thing in both directions, so it takes no flip. -->
      <VIcon :name="search" :size="28" />
    </div>
  </div>
</template>

<style scoped>
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--vectis-space-4);
}
.row {
  display: flex;
  align-items: center;
  gap: var(--vectis-space-4);
}
</style>

D'où vient le dessin

Le dessin est cherché dans un ordre fixe, et la première source qui répond est celle qui est dessinée :

  1. render, une description explicite de ce qu'il faut dessiner : des données de tracé SVG, un composant, une image, ou la classe d'une police.
  2. src, l'adresse d'une image.
  3. name, proposé à votre résolveur en premier, puis au dessin que porte une icône de la bibliothèque, puis à une police à ligatures.
  4. Le slot par défaut, un SVG en ligne, atteint quand ni render, ni src, ni name n'ont été donnés.
vue
render, as SVG path data
render, as a component
src, an image file
name, from the library
name, unresolved
an inline SVG, through the slot
<script setup lang="ts">
import { h } from 'vue'
import { VIcon } from 'vectis-ui'
import { ICON_VIEW_BOX, cloud_upload as cloudUpload, code, search } from 'vectis-ui/icons'

import firefoxLogo from '~/assets/img/firefox-browser-svg.svg'

/* A component icon, the shape an icon set such as Lucide ships: the contract is a
   single <svg> root. The drawing is borrowed from the library's own registry rather
   than redrawn here. */
const CodeIcon = () =>
  h('svg', { viewBox: ICON_VIEW_BOX, fill: 'currentColor' }, [h('path', { d: code.paths[0] })])
</script>

<template>
  <div class="grid">
    <!-- `render` wins over everything, and short-circuits the resolver with it. -->
    <figure>
      <VIcon :render="{ path: cloudUpload.paths[0] }" :size="28" />
      <figcaption>render, as SVG path data</figcaption>
    </figure>

    <figure>
      <VIcon :render="{ component: CodeIcon }" :size="28" />
      <figcaption>render, as a component</figcaption>
    </figure>

    <figure>
      <VIcon :src="firefoxLogo" :size="28" />
      <figcaption>src, an image file</figcaption>
    </figure>

    <!-- One of the library's own icons: a name travelling with its drawing. The
         resolver is still asked for that name first, and the drawing answers when
         nothing else does. -->
    <figure>
      <VIcon :name="search" :size="28" />
      <figcaption>name, from the library</figcaption>
    </figure>

    <!-- A plain string is only ever a name. Nothing in the registry answers to this
         one, so it is left to a ligature font, which this site does not load: what
         you see is the fallback, the name drawn as its own text. -->
    <figure>
      <VIcon name="translate" :size="28" />
      <figcaption>name, unresolved</figcaption>
    </figure>

    <!-- Last resort: the slot, reached when neither `name` nor `src` was given. -->
    <figure>
      <VIcon :size="28">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M12 4v16M4 12h16" stroke-linecap="round" />
        </svg>
      </VIcon>
      <figcaption>an inline SVG, through the slot</figcaption>
    </figure>
  </div>
</template>

<style scoped>
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: var(--vectis-space-5);
}
figure {
  display: grid;
  justify-items: center;
  gap: var(--vectis-space-2);
  margin: 0;
}
figcaption {
  color: var(--vectis-color-text-muted);
  font-size: var(--vectis-text-caption-size);
  text-align: center;
}
</style>

L'ordre est le contrat : votre résolveur passe avant les dessins de la bibliothèque, et un résolveur qui ne répond rien pour un nom donné le rend au lieu de laisser un trou, ce qui rend utilisable une correspondance partielle. Une simple chaîne n'est jamais qu'un nom, jamais une adresse. Brancher un jeu, et la liste de ce que la bibliothèque embarque, sont tous deux sur Iconographie.

API

Props

PropTypeDéfaut
namestring | BuiltinIconaucune
Quelle icône dessiner. Une simple chaîne est un nom : elle est proposée à votre résolveur, puis laissée à une police d'icônes en tant que ligature. Une des icônes de la bibliothèque, importée depuis vectis-ui/icons, porte son dessin avec elle ; le résolveur est tout de même interrogé d'abord, et le dessin répond quand rien d'autre ne le fait.
renderIconRenderaucune
Une description explicite de ce qu'il faut dessiner, une image, un composant, un tracé ou une classe, qui l'emporte sur tout le reste. C'est la voie que prend chaque prop d'icône de la bibliothèque quand on lui donne autre chose qu'un simple nom.
srcstringaucune
L'adresse d'une image à utiliser comme icône. Elle l'emporte sur name.
sizenumber | stringaucune
Une taille en pixels, en nombre ou en chaîne numérique. Sans elle, ou avec autre chose qu'un nombre, l'icône prend la taille que son contexte impose, un bouton en fixant une pour les icônes qu'il contient, et à défaut 1em, ce qui la fait suivre le texte alentour.
labelstringaucune
Ce que l'icône signifie, pour les lecteurs d'écran. L'omettre marque l'icône comme décorative et la masque à ces derniers, ce qui est juste dès que le texte alentour dit déjà ce qu'elle dit.
filledbooleanfalse
Dessine la version pleine de l'icône. Les icônes intégrées l'honorent partout où le remplissage change réellement le dessin, et une police à ligatures le fait toujours. Cela ne signifie rien pour une image ou un SVG en ligne, dont la forme est fixe.
mirroredbooleanfalse
Retourne l'icône horizontalement dans un contexte de droite à gauche, pour un glyphe qui désigne une direction physique : un chevron « précédent » pointe à gauche en français et à droite en arabe. Désactivé par défaut, la plupart des icônes disant la même chose dans les deux sens. La direction est celle que le navigateur a calculée, donc le dir d'un ancêtre suffit.

Slots

SlotType
default{}
Un SVG en ligne, utilisé quand ni src ni name n'a été donné.

Types

Les types que les tables ci-dessus nomment, écrits comme la librairie les déclare. Ceux qui portent export s'importent depuis vectis-ui pour typer votre propre code ; les autres décrivent la forme de ce qu'un slot fournit.

export interface BuiltinIcon {
  name: string
  paths: readonly [string] | readonly [string, string]
}
export type IconRender =
  | { path: string; viewBox?: string }
  | { component: Component; props?: Record<string, unknown> }
  | { src: string }
  | { text: string; class?: string }
  | { class: string }