Raccourci clavier : Ctrl + K
Commencer

Bouton icône

Un bouton carré portant une icône et aucun libellé. C'est VButton en dessous, avec deux valeurs par défaut à lui et un nom obligatoire, puisque l'image est tout ce qu'un lecteur d'écran aurait sinon.

Utilisation

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

<template>
  <VIconButton label="Search" :icon="search" />
</template>

Exemples

Variantes et tonalités

Les mêmes quatre variant et trois tone que VButton, avec deux valeurs par défaut à lui : ghost plutôt que solid, et neutral plutôt que accent.

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

const variants = ['solid', 'soft', 'outline', 'ghost'] as const
const tones = ['accent', 'neutral', 'danger'] as const
</script>

<template>
  <div v-for="tone in tones" :key="tone" class="row">
    <VIconButton
      v-for="variant in variants"
      :key="variant"
      :icon="notifications"
      :variant="variant"
      :tone="tone"
      :label="`Notifications, ${variant} ${tone}`"
    />
  </div>
</template>

<style scoped>
.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vectis-space-3);
}
</style>

Surélevé

elevated applique l'échelle d'ombres à la variante en cours. Les variantes ghost et outline gagnent en plus une surface surélevée.

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

const variants = ['solid', 'soft', 'outline', 'ghost'] as const
</script>

<template>
  <div class="row">
    <VIconButton
      v-for="variant in variants"
      :key="variant"
      :icon="notifications"
      :variant="variant"
      :label="`Notifications, ${variant}`"
    />
  </div>

  <div class="row">
    <VIconButton
      v-for="variant in variants"
      :key="variant"
      :icon="notifications"
      :variant="variant"
      elevated
      :label="`Notifications, ${variant} raised`"
    />
  </div>
</template>

<style scoped>
.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vectis-space-3);
}
</style>

Tailles

size définit la boîte, carrée à chacun des cinq paliers de 24 à 56 pixels. compact retire 4px des deux côtés, si bien que la boîte reste carrée.

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

const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const
</script>

<template>
  <div class="row">
    <VIconButton
      v-for="size in sizes"
      :key="size"
      :icon="search"
      :size="size"
      variant="outline"
      :label="`Search, ${size}`"
    />
  </div>

  <!-- Compact takes 4px off both sides, so the box stays square and the icon inside it
       keeps the size its step gives it. -->
  <div class="row">
    <VIconButton
      v-for="size in sizes"
      :key="size"
      :icon="search"
      :size="size"
      compact
      variant="outline"
      :label="`Search, ${size} compact`"
    />
  </div>
</template>

<style scoped>
.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--vectis-space-3);
}
</style>

Formes

shape choisit la silhouette, carrée ou circulaire. Dans un VButtonGroup, les règles d'angles de la rangée l'emportent et un segment circulaire garde des jonctions droites.

vue
<script setup lang="ts">
import { VButtonGroup, VIconButton } from 'vectis-ui'
import {
  arrow_downward as arrowDownward,
  arrow_upward as arrowUpward,
  close,
  swap_vert as swapVert,
} from 'vectis-ui/icons'

const sizes = ['sm', 'md', 'lg'] as const
</script>

<template>
  <div class="stack">
    <div class="row">
      <VIconButton
        v-for="size in sizes"
        :key="size"
        :icon="close"
        :size="size"
        variant="outline"
        :label="`Close, ${size}`"
      />
      <VIconButton
        v-for="size in sizes"
        :key="`${size}-circular`"
        :icon="close"
        :size="size"
        shape="circular"
        variant="outline"
        :label="`Close, circular ${size}`"
      />
    </div>

    <!-- Inside a group the corner rules are the row's, and they win: a circular segment
         keeps square seams so the row still reads as one object. Intended, and the
         reason a shape is worth choosing before grouping rather than after. -->
    <VButtonGroup variant="outline">
      <VIconButton :icon="arrowUpward" shape="circular" label="Sort ascending" />
      <VIconButton :icon="swapVert" shape="circular" label="Unsorted" />
      <VIconButton :icon="arrowDownward" shape="circular" label="Sort descending" />
    </VButtonGroup>
  </div>
</template>

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

Icônes

icon accepte toute valeur d'icône et iconFilled en demande la forme pleine. Le slot par défaut est la voie vers une icône que la prop ne peut pas exprimer, et reste décoratif : le bouton est nommé par son label.

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

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

<template>
  <!-- `icon` takes everything an icon prop in the library takes: one of its own icons,
       a bare name for your resolver, or an explicit render. -->
  <VIconButton :icon="search" variant="outline" label="Search" />
  <VIconButton icon="translate" variant="outline" label="Translate" />
  <VIconButton :icon="{ path: code.paths[0] }" variant="outline" label="View the source" />
  <VIconButton :icon="{ src: firefoxLogo }" variant="outline" label="Open in Firefox" />

  <!-- Filled marks a state, here a notification that has arrived. -->
  <VIconButton :icon="notifications" icon-filled variant="outline" label="3 new notifications" />

  <!-- The slot is the way to an icon the prop cannot express: a VIcon you configure
       yourself, or an inline SVG. The button is already named by its label, so whatever
       goes in here stays decorative. -->
  <VIconButton variant="outline" label="Notifications, larger glyph">
    <VIcon :name="notifications" :size="28" />
  </VIconButton>
  <VIconButton variant="outline" label="Add">
    <svg :viewBox="ICON_VIEW_BOX" fill="none" stroke="currentColor" stroke-width="80">
      <path d="M480-800v640M160-480h640" stroke-linecap="round" />
    </svg>
  </VIconButton>
</template>

href rend le bouton comme une ancre, aux conditions de VButton. Un lien désactivé garde sa place et perd sa destination.

vue
<script setup lang="ts">
import { VIconButton } from 'vectis-ui'
import { arrow_right_alt as arrowRightAlt, code } from 'vectis-ui/icons'
</script>

<template>
  <!-- `href` renders an <a> instead of a <button>. -->
  <VIconButton href="#usage" :icon="arrowRightAlt" variant="outline" label="Back to usage" />

  <VIconButton
    href="https://github.com"
    target="_blank"
    rel="noreferrer"
    :icon="code"
    variant="outline"
    label="View the source, opens in a new tab"
  />

  <!-- A disabled link keeps its place and loses its destination: the href is removed
       and the clicks are dropped, since nothing in HTML disables an anchor. -->
  <VIconButton href="#usage" :icon="arrowRightAlt" variant="outline" disabled label="Unavailable" />
</template>

États

disabled grise le bouton par les tokens de couleur. loading place un indicateur dans la boîte de l'icône et désactive le bouton pendant qu'il tourne.

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

const variants = ['solid', 'soft', 'outline', 'ghost'] as const
</script>

<template>
  <div class="row">
    <VIconButton
      v-for="variant in variants"
      :key="variant"
      :icon="notifications"
      :variant="variant"
      disabled
      :label="`Notifications, ${variant} disabled`"
    />
  </div>

  <!-- Loading puts a spinner where the icon was and disables the button while it turns,
       so the same action cannot be asked for twice. The spinner takes the icon's box,
       which is what keeps the square from changing size. -->
  <div class="row">
    <VIconButton :icon="notifications" loading label="Refreshing" />
    <VIconButton :icon="notifications" variant="outline" loading label="Checking" />
    <VIconButton :icon="notifications" variant="ghost" loading label="Loading" />
  </div>
</template>

<style scoped>
.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vectis-space-3);
}
</style>

API

Props

PropTypeDéfaut
labelstringaucune
Ce que fait le bouton, en mots. Cela devient l'aria-label et c'est la seule chose dont dispose un lecteur d'écran : nommez donc l'action, « Fermer », « Mois suivant », plutôt que l'image.
variantButtonVariant'solid' | 'outline' | 'ghost' | 'soft''ghost'
Le poids visuel que porte le bouton, sur l'échelle de VButton. Dans un VButtonGroup, c'est le groupe qui en décide.
toneButtonTone'accent' | 'neutral' | 'danger''neutral'
Ce que l'action signifie, en couleur. Un bouton réduit à une icône relève le plus souvent du décor, et c'est pourquoi il part en neutre là où VButton part en accent. Omis dans un VButtonGroup, il prend celui du groupe.
elevatedbooleanfalse
Soulève le bouton avec une ombre, et une surface surélevée sur ghost et outline.
sizeButtonSize'xs' | 'sm' | 'md' | 'lg' | 'xl''md'
La taille du carré, tirée de l'échelle partagée par tous les contrôles.
compactbooleanfalse
Retire 4px des deux côtés du carré, qui reste carré.
shapeIconButtonShape'square' | 'circular''square'
La silhouette : un carré portant le rayon de coin commun à tous les contrôles, ou un cercle. La boîte reste carrée dans les deux cas, seuls les coins changent.
hrefstringaucune
Transforme le bouton en <a> pointant vers cette adresse. Un lien désactivé ou en chargement devient inerte : l'adresse est retirée, si bien qu'il ne peut être ni focalisé ni suivi.
typeButtonHTMLAttributes['type']'button'
Le type natif du bouton. Il est ignoré dès que href en fait un lien.
disabledbooleanfalse
Rend le bouton inutilisable, grisé par les tokens de couleur.
loadingbooleanfalse
Remplace l'icône par un indicateur et désactive le bouton pendant qu'il tourne.
iconIconSourceaucune
L'icône à afficher. Le slot par défaut est la voie pour en fournir une que cette prop ne peut pas exprimer.
iconFilledbooleanfalse
Rend l'icône dans sa forme pleine, l'axe FILL de la police.

Slots

SlotType
default{}
L'icône, quand la prop icon ne peut pas l'exprimer : un VIcon, ou un SVG en ligne marqué aria-hidden, le bouton étant déjà nommé par son libellé.

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 }
export type IconSource = string | BuiltinIcon | IconRender