Raccourci clavier : Ctrl + K
Commencer

Case à cocher

Un choix qu'un envoi exécutera, à la différence d'un interrupteur, qui agit sur-le-champ. Elle enveloppe un vrai <input type="checkbox">, donc elle s'envoie avec le formulaire.

Utilisation

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

const subscribed = ref(true)
</script>

<template>
  <VCheckbox v-model="subscribed">Send me release notes</VCheckbox>
</template>

Exemples

Aide

label écrit le texte à côté de la case, et le slot par défaut le remplace quand le libellé demande plus que du texte. hint ajoute une légende en dessous, reliée à la case par aria-describedby et gardée hors du <label> : elle est annoncée comme une description et non comme une partie du nom.

vue
A summary of the week, every Monday.Only when someone names you.
<script setup lang="ts">
import { ref } from 'vue'
import { VCheckbox } from 'vectis-ui'

const digest = ref(true)
const mentions = ref(false)
</script>

<template>
  <div class="stack">
    <!-- The hint is tied to the box through aria-describedby, and it sits outside the
         label, so a screen reader reads it after the name rather than as part of it. -->
    <VCheckbox v-model="digest" label="Weekly digest" hint="A summary of the week, every Monday." />
    <VCheckbox v-model="mentions" label="Mentions" hint="Only when someone names you." />
  </div>
</template>

<style scoped>
.stack {
  display: grid;
  justify-items: start;
  gap: var(--vectis-space-3);
}
</style>

Position du libellé

labelPosition place le libellé avant la case plutôt qu'après.

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

<template>
  <div class="stack">
    <VCheckbox>Label after the box, the default</VCheckbox>
    <VCheckbox label-position="start">Label before the box</VCheckbox>
  </div>
</template>

<style scoped>
/* `justify-items: start` keeps each row as wide as its own label: the clickable area is
   the whole <label>, so a stretched row would be clickable well past its text. */
.stack {
  display: grid;
  justify-items: start;
  gap: var(--vectis-space-2);
}
</style>

Écartement

spread prend toute la largeur offerte et pousse le libellé et la case aux deux extrémités de la ligne.

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

const analytics = ref(true)
const crashes = ref(false)
</script>

<template>
  <div class="settings">
    <VCheckbox v-model="analytics" spread>Share anonymous usage data</VCheckbox>
    <VCheckbox v-model="crashes" spread label-position="start">Send crash reports</VCheckbox>
  </div>
</template>

<style scoped>
/* A spread row takes the width it is given, so the panel is what decides how far apart
   the label and the box end up. */
.settings {
  display: grid;
  gap: var(--vectis-space-3);
  inline-size: 100%;
  max-inline-size: 24rem;
  padding: var(--vectis-space-4);
  border: 1px solid var(--vectis-color-border);
  border-radius: var(--vectis-radius-surface);
}
</style>

Indéterminé

indeterminate affiche un tiret à la place de la coche. C'est une apparence à part : le v-model contient toujours true ou false.

vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import { VCheckbox } from 'vectis-ui'

const scopes = ref([
  { label: 'Read', granted: true },
  { label: 'Write', granted: false },
  { label: 'Delete', granted: false },
])

const all = computed({
  get: () => scopes.value.every((scope) => scope.granted),
  set: (value: boolean) => {
    scopes.value.forEach((scope) => {
      scope.granted = value
    })
  },
})

/* The dash is a third appearance and not a third value: the parent is genuinely unticked
   here, and `indeterminate` is what draws it as partially checked. */
const some = computed(() => scopes.value.some((scope) => scope.granted) && !all.value)
</script>

<template>
  <div class="tree">
    <VCheckbox v-model="all" :indeterminate="some">Permissions</VCheckbox>
    <div class="children">
      <VCheckbox v-for="scope in scopes" :key="scope.label" v-model="scope.granted">
        {{ scope.label }}
      </VCheckbox>
    </div>
  </div>
</template>

<style scoped>
.tree,
.children {
  display: grid;
  justify-items: start;
  gap: var(--vectis-space-2);
}
.children {
  padding-inline-start: var(--vectis-space-6);
}
</style>

Lecture seule

readonly montre l'état sans permettre de le changer. L'attribut natif n'a aucun effet sur une case à cocher, donc le composant annule le clic, ce qui couvre aussi la barre d'espace. La case reste focalisable, s'envoie avec son formulaire et est annoncée en lecture seule. Elle participe toujours à la validation de contrainte, cela dit, donc readonly avec required et rien de coché laisse un formulaire impossible à envoyer comme à corriger.

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

const on = ref(true)
const off = ref(false)
</script>

<template>
  <div class="stack">
    <!-- Still focusable and still submitted with the form, but a click or the Space key
         changes nothing. -->
    <VCheckbox v-model="on" readonly label="Set by your organisation" />
    <VCheckbox v-model="off" readonly label="Not available on your plan" />
  </div>
</template>

<style scoped>
.stack {
  display: grid;
  justify-items: start;
  gap: var(--vectis-space-3);
}
</style>

Désactivé

disabled empêche de cocher la case et la grise par les tokens de couleur. Le clavier l'enjambe.

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

const off = ref(false)
const on = ref(true)
</script>

<template>
  <div class="stack">
    <VCheckbox v-model="off" disabled>Unticked</VCheckbox>
    <VCheckbox v-model="on" disabled>Ticked</VCheckbox>
    <VCheckbox v-model="off" disabled indeterminate>Partially ticked</VCheckbox>
  </div>
</template>

<style scoped>
.stack {
  display: grid;
  justify-items: start;
  gap: var(--vectis-space-2);
}
</style>

API

Props

PropTypeDéfaut
labelstringaucune
Le texte à côté de la case, qui la nomme. Le slot par défaut le remplace.
hintstringaucune
Une ligne d'aide sous le libellé. Elle est reliée à la case pour les technologies d'assistance, qui la lisent après le libellé et non comme une partie de celui-ci.
indeterminatebooleanfalse
Affiche la case comme partiellement cochée, un tiret au lieu d'une coche. C'est l'allure d'une case parente dont certains enfants sont cochés et d'autres non. C'est un état à part, pas une valeur que le v-model peut porter.
labelPositionCheckboxLabelPosition'start' | 'end''end'
De quel côté de la case se place le libellé.
spreadbooleanfalse
Pousse le libellé et la case aux extrémités opposées de la ligne, qui prend toute la largeur disponible. C'est la forme habituelle d'une liste de réglages.
invalidbooleanfalse
Marque le champ comme invalide, ce qui colore la case et le signale aux technologies d'assistance. À utiliser pour une règle que le navigateur ne sait pas vérifier seul ; la validité native est déjà prise en charge sans elle.
disabledbooleanfalse
Rend la case inutilisable, grisée par les tokens de couleur.
readonlybooleanfalse
Montre l'état sans permettre de le changer. La case reste focalisable, est annoncée en lecture seule et s'envoie toujours avec son formulaire ; un clic ou la barre d'espace ne changent simplement rien.
v-modelbooleanfalse
Si la case est cochée. Elle part décochée, et le tiret est une troisième apparence plutôt qu'une troisième valeur : celle-là, c'est indeterminate.

Slots

SlotType
default{}
Le libellé, quand il demande plus que le texte de la prop label. Il est cliquable.

Variables CSS

TokenValeur
--vectis-control-size-check1.25rem
--vectis-control-size-check-mark0.875rem