Raccourci clavier : Ctrl + K
Commencer

Puce

Une petite information : un statut, une étiquette, un filtre qui reste choisi. Elle partage mot pour mot sa table de variantes et de tons avec VButton, et ajoute les deux états qu'un bouton n'a pas.

Utilisation

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

<template>
  <VChip>Design system</VChip>
</template>

Exemples

Variantes et tonalités

variant propose trois façons de peindre la puce, soft, solid et outline, et tone cinq sens.

vue
neutral softneutral solidneutral outline
accent softaccent solidaccent outline
success softsuccess solidsuccess outline
warning softwarning solidwarning outline
danger softdanger soliddanger outline
<script setup lang="ts">
import { VChip } from 'vectis-ui'

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

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

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

Silhouettes

shape choisit la silhouette : chip prend le rayon d'angle d'un contrôle interactif, pill arrondit complètement les extrémités. Les coins de chip lisent --vectis-radius-chip, qui pointe vers --vectis-radius-interactive depuis :root : redéfinissez-le pour arrondir les puces indépendamment des autres contrôles. Posé sur un sélecteur plus étroit que :root, un override de --vectis-radius-interactive n'atteint pas les puces : donnez alors les deux tokens à ce sélecteur.

vue
chip softchip solidchip outline
pill softpill solidpill outline
<script setup lang="ts">
import { VChip } from 'vectis-ui'

const variants = ['soft', 'solid', 'outline'] as const
const shapes = ['chip', 'pill'] as const
</script>

<template>
  <div v-for="shape in shapes" :key="shape" class="row">
    <VChip
      v-for="variant in variants"
      :key="variant"
      :shape="shape"
      :variant="variant"
      tone="accent"
    >
      {{ shape }} {{ variant }}
    </VChip>
  </div>
</template>

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

Tailles

size définit la hauteur à 24 ou 32 pixels, et compact lui retire 4px.

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

<template>
  <div class="row">
    <VChip size="xs">Extra small</VChip>
    <VChip size="sm">Small</VChip>
  </div>

  <div class="row">
    <VChip size="xs" compact>Extra small</VChip>
    <VChip size="sm" compact>Small</VChip>
  </div>
</template>

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

Couleurs personnalisées

color remplace le ton, toutes les nuances nécessaires en étant dérivées. Elle accepte n'importe quelle couleur CSS.

vue
softsolidoutline
#0f766emediumvioletredoklch(0.55 0.15 150)
<script setup lang="ts">
import { ref } from 'vue'
import { VChip } from 'vectis-ui'

const selected = ref(true)
</script>

<template>
  <div class="row">
    <VChip color="#7c3aed" variant="soft">soft</VChip>
    <VChip color="#7c3aed" variant="solid">solid</VChip>
    <VChip color="#7c3aed" variant="outline">outline</VChip>
    <VChip v-model:selected="selected" color="#7c3aed" selectable check>selectable</VChip>
  </div>

  <div class="row">
    <VChip color="#0f766e">#0f766e</VChip>
    <VChip color="mediumvioletred">mediumvioletred</VChip>
    <VChip color="oklch(0.55 0.15 150)">oklch(0.55 0.15 150)</VChip>
  </div>
</template>

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

Avec des icônes

iconStart et iconEnd posent une icône de part et d'autre du libellé, et les slots #start et #end les remplacent. iconFilled dessine les deux icônes pleines. Une puce sans libellé devient carrée et doit recevoir un nom.

vue
Start iconEnd iconBoth Operational
<script setup lang="ts">
import { VChip } from 'vectis-ui'
import { arrow_right_alt as arrowRightAlt, notifications, schedule } from 'vectis-ui/icons'
</script>

<template>
  <VChip :icon-start="schedule" tone="accent">Start icon</VChip>
  <VChip :icon-end="arrowRightAlt" tone="accent">End icon</VChip>
  <VChip :icon-start="schedule" :icon-end="arrowRightAlt" tone="accent">Both</VChip>

  <!-- No label at all: the chip becomes square, and the button it already is takes the name. -->
  <VChip :icon-start="notifications" tone="danger" clickable aria-label="Notifications" />

  <VChip tone="success">
    <template #start><span class="dot" /></template>
    Operational
  </VChip>
</template>

<style scoped>
/* The #start slot takes anything, not only an icon. `currentcolor` is the chip's own text
   colour, so the dot follows the tone with nothing to declare twice. */
.dot {
  inline-size: 0.5rem;
  aspect-ratio: 1;
  border-radius: 50%;
  background: currentcolor;
}
</style>

clickable rend la puce sous forme de bouton et href sous forme de lien. Sans l'un ni l'autre, c'est du texte simple.

vue
Static, no hover vuejs.org
<script setup lang="ts">
import { ref } from 'vue'
import { VChip } from 'vectis-ui'
import { arrow_right_alt as arrowRightAlt } from 'vectis-ui/icons'

const count = ref(0)
</script>

<template>
  <VChip>Static, no hover</VChip>
  <VChip clickable tone="accent" @click="count += 1">Clicked {{ count }} times</VChip>
  <VChip :icon-end="arrowRightAlt" href="https://vuejs.org" target="_blank" rel="noreferrer">
    vuejs.org
  </VChip>
</template>

Sélection

selectable transforme la puce en bascule liée à v-model:selected. check ajoute une coche avant le libellé, à la place de l'icône de début, et checkIcon change son glyphe.

vue
<script setup lang="ts">
import { ref } from 'vue'
import { VChip } from 'vectis-ui'
import { check_circle as checkCircle } from 'vectis-ui/icons'

const frameworks = ref([
  { label: 'Vue', on: true },
  { label: 'React', on: false },
  { label: 'Svelte', on: false },
])

const filters = ref([
  { label: 'Open', on: true },
  { label: 'Assigned to me', on: true },
  { label: 'Archived', on: false },
])

const labels = ref([
  { label: 'Bug', on: true },
  { label: 'Feature', on: false },
  { label: 'Docs', on: false },
])
</script>

<template>
  <div class="row" role="group" aria-label="Frameworks">
    <VChip
      v-for="framework in frameworks"
      :key="framework.label"
      v-model:selected="framework.on"
      selectable
      tone="accent"
    >
      {{ framework.label }}
    </VChip>
  </div>

  <div class="row" role="group" aria-label="Filters">
    <VChip
      v-for="filter in filters"
      :key="filter.label"
      v-model:selected="filter.on"
      selectable
      check
      tone="accent"
    >
      {{ filter.label }}
    </VChip>
  </div>

  <div class="row" role="group" aria-label="Labels">
    <VChip
      v-for="item in labels"
      :key="item.label"
      v-model:selected="item.on"
      selectable
      check
      :check-icon="checkCircle"
      tone="accent"
    >
      {{ item.label }}
    </VChip>
  </div>
</template>

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

Suppression

dismissible ajoute un second bouton qui émet dismiss, le retrait de la liste vous revenant. dismissIcon et dismissLabel changent son glyphe et ses mots. Dans une rangée de puces, donnez à chaque croix un dismissLabel qui nomme ce qu'elle retire, sans quoi toutes sont annoncées avec le même mot.

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

const ALL = ['Vue', 'TypeScript', 'CSS', 'Vite']

/* The chip only asks to be removed. Taking it out of the list is this component's
   decision, which is what lets the same event archive, undo or confirm instead. */
const tags = ref([...ALL])

function remove(tag: string) {
  tags.value = tags.value.filter((current) => current !== tag)
}
</script>

<template>
  <div class="row">
    <VChip v-for="tag in tags" :key="tag" tone="accent" dismissible @dismiss="remove(tag)">
      {{ tag }}
    </VChip>
    <VButton
      v-if="tags.length < ALL.length"
      variant="ghost"
      tone="neutral"
      size="xs"
      @click="tags = [...ALL]"
    >
      Reset
    </VButton>
  </div>
</template>

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

États

disabled grise la puce par les tokens de couleur. Un lien désactivé voit son adresse retirée, ce qui le laisse ni focalisable ni suivable.

vue
softsolidoutline
Inert linkDismissible
<script setup lang="ts">
import { VChip } from 'vectis-ui'

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

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

  <div class="row">
    <VChip clickable disabled>Clickable</VChip>
    <VChip href="https://vuejs.org" disabled>Inert link</VChip>
    <VChip selectable check :selected="true" tone="accent" disabled>Selected</VChip>
    <VChip dismissible disabled>Dismissible</VChip>
  </div>
</template>

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

API

Props

PropTypeDéfaut
variantChipVariant'soft' | 'solid' | 'outline''soft'
L'intensité avec laquelle la puce est peinte : un fond teinté, la couleur pleine, ou une bordure seule.
toneChipTone'neutral' | 'accent' | 'danger' | 'success' | 'warning''neutral'
Ce que la puce signifie, exprimé en couleur. Une puce peut rapporter un état là où un bouton ne le peut pas, et c'est pourquoi elle en propose cinq plutôt que trois.
colorstringaucune
Une couleur à vous, en hexadécimal, en nom CSS ou en oklch(), qui remplace le ton. Toutes les nuances nécessaires sont dérivées de cette seule couleur, si bien qu'elle suit les deux thèmes sans rien à reconstruire. Seul le contraste du texte sur une puce en couleur pleine reste à votre charge.
shapeChipShape'chip' | 'pill''chip'
La silhouette : des coins doucement arrondis, ou une pilule complète.
sizeChipSize'xs' | 'sm''xs'
La hauteur de la puce.
compactbooleanfalse
Retire 4px à la hauteur, en laissant le rembourrage, le texte et les icônes tels quels.
clickablebooleanfalse
Fait de la puce un bouton qui réagit au clic, sans retenir d'état.
hrefstringaucune
Où la puce mène, ce qui en fait un lien.
selectablebooleanfalse
Fait de la puce quelque chose qui reste choisi. Cela l'emporte sur href et clickable.
checkbooleanfalse
Affiche une coche avant le libellé tant que la puce est sélectionnée. Elle remplace l'icône de début qui aurait été donnée, si bien que les deux ne sont jamais montrées ensemble.
checkIconIconSourcecheck
L'icône de cette coche, une coche intégrée par défaut. iconFilled ne l'atteint pas.
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 iconStart et iconEnd dans leur forme pleine, l'axe FILL de la police. Sans effet sur les slots, ni sur la coche ou la croix de retrait.
dismissiblebooleanfalse
Ajoute un bouton qui demande le retrait de la puce. Il ne fait qu'émettre cette demande : retirer la puce est votre décision.
dismissIconIconSourceclose
L'icône de ce bouton de retrait.
dismissLabelstringaucune
Ce que fait le bouton de retrait, en mots. Il retombe sur le dictionnaire du design system.
disabledbooleanfalse
Rend la puce inutilisable, grisée par les tokens de couleur.
v-model:selectedbooleanfalse
Si la puce est sélectionnée, ce qui est aussi ce qui la rend sélectionnable : la lier transforme la puce en bouton bascule et l'emporte sur href et clickable.

Événements

ÉvénementType
dismiss[]
Le bouton de retrait a été pressé. La puce est toujours à l'écran : la retirer vous revient.

Slots

SlotType
default{}
Le libellé. Il peut être omis entièrement, ce qui donne une puce faite d'icônes seules.
start{}
Du contenu avant le libellé, qui prend la place de iconStart.
end{}
Du contenu après le libellé, qui prend la place de iconEnd.

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