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.
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>
En tant que lien
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
Prop
Type
Défaut
label
string
aucune
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.
Le poids visuel que porte le bouton, sur l'échelle de VButton. Dans un VButtonGroup, c'est le groupe qui en décide.
tone
ButtonTone'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.
elevated
boolean
false
Soulève le bouton avec une ombre, et une surface surélevée sur ghost et outline.
size
ButtonSize'xs' | 'sm' | 'md' | 'lg' | 'xl'
'md'
La taille du carré, tirée de l'échelle partagée par tous les contrôles.
compact
boolean
false
Retire 4px des deux côtés du carré, qui reste carré.
shape
IconButtonShape'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.
href
string
aucune
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.
type
ButtonHTMLAttributes['type']
'button'
Le type natif du bouton. Il est ignoré dès que href en fait un lien.
disabled
boolean
false
Rend le bouton inutilisable, grisé par les tokens de couleur.
loading
boolean
false
Remplace l'icône par un indicateur et désactive le bouton pendant qu'il tourne.
L'icône à afficher. Le slot par défaut est la voie pour en fournir une que cette prop ne peut pas exprimer.
iconFilled
boolean
false
Rend l'icône dans sa forme pleine, l'axe FILL de la police.
Slots
Slot
Type
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.