Raccourci clavier : Ctrl + K
Commencer

Bouton

Le bouton qui déclenche une action, et la référence dont sont tirées les tables de tons et de variantes de tous les autres composants colorés. Il rend un <button> natif, ou un <a> dès qu'on lui donne un href.

Utilisation

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

<template>
  <VButton>Save changes</VButton>
</template>

Exemples

Variantes et tons

variant propose quatre façons de peindre le bouton, et tone trois sens : accent, neutral et danger.

vue
<script setup lang="ts">
import { VButton } from 'vectis-ui'

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">
    <VButton v-for="variant in variants" :key="variant" :variant="variant" :tone="tone">
      {{ variant }}
    </VButton>
  </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. Un bouton ghost ou outline gagne en plus un fond surélevé.

vue
<script setup lang="ts">
import { VButton } from 'vectis-ui'

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

<template>
  <div class="row">
    <VButton v-for="variant in variants" :key="variant" :variant="variant">
      {{ variant }}
    </VButton>
  </div>

  <div class="row">
    <VButton v-for="variant in variants" :key="variant" :variant="variant" elevated>
      {{ variant }}
    </VButton>
  </div>
</template>

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

Tailles

size définit la hauteur : 24, 32, 40, 48 ou 56 pixels. La typographie, les rembourrages et les icônes suivent.

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

<template>
  <VButton size="xs">Extra small</VButton>
  <VButton size="sm">Small</VButton>
  <VButton size="md">Medium</VButton>
  <VButton size="lg">Large</VButton>
  <VButton size="xl">Extra large</VButton>
</template>

Compact

compact retire 4px à la hauteur, sans rien déplacer d'autre.

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

<template>
  <VButton size="sm">Small</VButton>
  <VButton size="sm" compact>Small compact</VButton>
  <VButton size="md">Medium</VButton>
  <VButton size="md" compact>Medium compact</VButton>
  <VButton size="lg">Large</VButton>
  <VButton size="lg" compact>Large compact</VButton>
</template>

Pleine largeur

fullWidth étire le bouton sur toute la largeur de son parent et le passe en bloc.

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

<template>
  <div class="column">
    <VButton>Save</VButton>
    <VButton variant="outline" tone="neutral">Cancel</VButton>
  </div>

  <div class="column">
    <VButton full-width>Save</VButton>
    <VButton full-width variant="outline" tone="neutral">Cancel</VButton>
  </div>
</template>

<style scoped>
/* Both columns are the same width and align their items to the start, so what widens
   the second pair is the prop and not the layout around it. */
.column {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: var(--vectis-space-3);
  inline-size: 220px;
}
</style>

Avec des icônes

iconStart et iconEnd posent une icône de part et d'autre du libellé, et iconFilled les passe à leur forme pleine. Les slots #start et #end prennent le relais quand le contenu est plus qu'une icône.

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

<template>
  <VButton :icon-start="search">Search</VButton>
  <VButton :icon-end="arrowRightAlt">Next</VButton>
  <VButton :icon-start="search" :icon-end="arrowRightAlt">Search and go</VButton>
  <VButton :icon-start="notifications" variant="outline" tone="neutral">Notify me</VButton>
  <VButton :icon-start="notifications" icon-filled variant="outline" tone="neutral">
    Notifying
  </VButton>
</template>

Icônes personnalisées

Les deux props d'icône acceptent un IconSource : une des icônes de la bibliothèque, un nom confié au résolveur installé par votre application, des données de tracé SVG, un composant, ou une image.

vue
<script setup lang="ts">
import { h } from 'vue'
import { VButton } 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.
const CodeIcon = () =>
  h('svg', { viewBox: ICON_VIEW_BOX, fill: 'currentColor' }, [h('path', { d: code.paths[0] })])
</script>

<template>
  <VButton :icon-start="search">A library icon</VButton>
  <VButton icon-start="translate" variant="outline" tone="neutral">A name</VButton>
  <VButton :icon-start="{ path: cloudUpload.paths[0] }" variant="outline" tone="neutral">
    SVG path data
  </VButton>
  <VButton :icon-start="{ component: CodeIcon }" variant="outline" tone="neutral">
    A component
  </VButton>
  <VButton :icon-start="{ src: firefoxLogo }" variant="outline" tone="neutral">An image</VButton>
</template>

href rend le bouton sous forme de <a>. Un lien désactivé ou en chargement est rendu inerte, son adresse retirée.

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

<template>
  <VButton href="#usage" :icon-end="arrowRightAlt">Back to usage</VButton>
  <VButton href="#usage" variant="outline" tone="neutral" disabled>Unavailable</VButton>
</template>

États

disabled grise le bouton par les tokens de couleur. loading le désactive, l'annonce occupé et place un indicateur là où était l'icône de début.

vue
<script setup lang="ts">
import { VButton } from 'vectis-ui'

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

<template>
  <div class="row">
    <VButton v-for="variant in variants" :key="variant" :variant="variant" disabled>
      {{ variant }}
    </VButton>
  </div>

  <div class="row">
    <VButton loading>Saving</VButton>
    <VButton variant="outline" tone="neutral" loading>Checking</VButton>
  </div>
</template>

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

API

Props

PropTypeDéfaut
variantButtonVariant'solid' | 'outline' | 'ghost' | 'soft''solid'
Le poids visuel que porte l'action : solid est rempli du ton, soft utilise un fond teinté, outline ne garde qu'une bordure, et ghost ne montre rien jusqu'au survol. Dans un VButtonGroup, c'est le groupe qui en décide, comme de la taille, de la densité et de l'élévation.
toneButtonTone'accent' | 'neutral' | 'danger''accent'
Ce que l'action signifie : accent pour l'action ordinaire, neutral pour une action secondaire, danger pour celle qui détruit quelque chose. Sur un bouton, un ton est une intention, et c'est pourquoi des états comme succès ou avertissement ne sont pas proposés ici. Omis dans un VButtonGroup, il prend celui du groupe ; seul, le bouton est en accent.
elevatedbooleanfalse
Soulève le bouton de la page avec l'échelle d'ombres, quelle que soit la variante. Un bouton ghost ou outline reçoit en plus une surface surélevée, parce qu'en thème sombre une ombre posée sur le fond de page n'a rien qui la projette.
sizeButtonSize'xs' | 'sm' | 'md' | 'lg' | 'xl''md'
La hauteur du bouton, tirée de l'échelle de tailles partagée par tous les contrôles : 24, 32, 40, 48 et 56 pixels.
compactbooleanfalse
Retire 4px à la hauteur, en laissant le rembourrage, le texte et les icônes tels quels.
fullWidthbooleanfalse
Étire le bouton sur toute la largeur de son parent au lieu de le laisser à la largeur de son libellé. Il devient également un élément de bloc, et ne repose donc plus sur une ligne de texte.
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 : il cesse de répondre, quitte l'ordre de tabulation et se grise par les tokens de couleur plutôt que par l'opacité.
loadingbooleanfalse
Affiche un indicateur, désactive le bouton et l'annonce comme occupé. L'indicateur prend la place de l'icône de début, si bien que les deux ne sont jamais côte à côte.
iconStartIconSourceaucune
Une icône avant le libellé. Le slot #start la remplace.
iconEndIconSourceaucune
Une icône après le libellé. Le slot #end la remplace.
iconFilledbooleanfalse
Rend les deux icônes dans leur forme pleine, l'axe FILL de la police. Sans effet sur les slots #start et #end, dont vous construisez vous-même les icônes.

Slots

SlotType
default{}
Le libellé du bouton.
start{}
Du contenu placé avant le libellé, en général une icône. Marquez-la aria-hidden quand elle ne fait que répéter ce que le libellé dit déjà.
end{}
Du contenu placé après le 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