Raccourci clavier : Ctrl + K
Commencer

Zone de texte

Un champ de texte multiligne, avec le même décor que VInput : libellé au-dessus, indication en dessous, icônes à l'intérieur, compteur et bouton d'effacement. Il peut grandir à mesure que le texte est saisi.

Utilisation

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

const message = ref('')
</script>

<template>
  <VTextarea v-model="message" label="Message" placeholder="What would you like to tell us?" />
</template>

Exemples

Libellé et indication

label est un vrai <label> lié au champ : cliquer les mots place le curseur dans la boîte. hint passe sous le champ et lui est lié par aria-describedby.

vue

Two or three sentences. It appears on your public profile.

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

const bio = ref('')
</script>

<template>
  <VTextarea
    v-model="bio"
    label="Short bio"
    hint="Two or three sentences. It appears on your public profile."
    placeholder="What do you work on?"
  />
</template>

Tailles

size pose les rembourrages, l'échelle typographique et les icônes, jamais la hauteur, qui vient de rows. compact retire 4px aux rembourrages à chacune des trois tailles.

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

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

<template>
  <div class="grid">
    <template v-for="size in sizes" :key="size">
      <VTextarea :size="size" :label="size" :rows="2" />
      <VTextarea :size="size" :label="`${size} compact`" :rows="2" compact />
    </template>
  </div>
</template>

<style scoped>
/* Two columns wherever there is room for them, so each size is read against its own
   compact form rather than against the size above it. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: var(--vectis-space-4);
}
</style>

Icônes

iconStart et iconEnd posent une icône décorative à chaque extrémité, sur la première ligne plutôt qu'au milieu de la boîte. Le slot #end remplace l'icône de fin, là où #start est rendu après l'icône de début plutôt qu'à sa place.

vue
<script setup lang="ts">
import { VTextarea } from 'vectis-ui'
import { description, info } from 'vectis-ui/icons'
</script>

<template>
  <VTextarea :icon-start="description" label="Start icon" :rows="2" />
  <VTextarea :icon-end="info" label="End icon" :rows="2" />
  <VTextarea :icon-start="description" :icon-end="info" label="Both" :rows="2" />
</template>

Icônes cliquables

Un écouteur @click:icon-start ou @click:icon-end transforme l'icône en vrai bouton, qui demande alors son libellé. Chaque bouton est son propre arrêt de tabulation et reste hors de la zone de saisie.

vue

Nothing attached yet.

<script setup lang="ts">
import { computed, ref } from 'vue'
import { VTextarea } from 'vectis-ui'
import { attach_file as attachFile, code } from 'vectis-ui/icons'

const message = ref('')
const attachments = ref(0)

const hint = computed(() => {
  if (attachments.value === 0) return 'Nothing attached yet.'
  return attachments.value === 1 ? '1 file attached.' : `${attachments.value} files attached.`
})

function insertCodeBlock() {
  message.value += '\n```\n\n```'
}
</script>

<template>
  <VTextarea
    v-model="message"
    label="Message"
    :hint="hint"
    :rows="4"
    :icon-start="code"
    icon-start-label="Insert a code block"
    :icon-end="attachFile"
    icon-end-label="Attach a file"
    @click:icon-start="insertCodeBlock"
    @click:icon-end="attachments += 1"
  />
</template>

Effaçable

clearable ajoute une croix qui vide le champ, affichée tant qu'il y a quelque chose à vider et que le champ est modifiable. L'appuyer rend aussitôt le focus à la zone de saisie, et clear est émis après coup.

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

const draft = ref('A first attempt, worth throwing away in one go.')
</script>

<template>
  <VTextarea v-model="draft" label="Draft" clearable :rows="3" />
</template>

Compteurs

counter passe sous le champ, à côté du texte d'aide. Face à maxlength, le navigateur refuse tout ce qui dépasse la limite, là où softLimit laisse le lecteur continuer : le compteur passe au rouge et le champ se déclare invalide par la validité native. Il compte des caractères, comme sur VInput ; sur VFileInput, la même prop compte des fichiers et leur taille.

vue

The browser refuses the eighty-first character.

22/80

Type past eighty and the field goes into error instead.

0/80

No limit, so the counter only counts.

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

const summary = ref('Vue developer in Lyon.')
const review = ref('')
const note = ref('')
</script>

<template>
  <VTextarea
    v-model="summary"
    label="Summary"
    hint="The browser refuses the eighty-first character."
    :maxlength="80"
    counter
    :rows="2"
  />

  <VTextarea
    v-model="review"
    label="Review"
    hint="Type past eighty and the field goes into error instead."
    :maxlength="80"
    soft-limit
    counter
    :rows="3"
  />

  <VTextarea
    v-model="note"
    label="Note"
    hint="No limit, so the counter only counts."
    counter
    :rows="2"
  />
</template>

Croissance automatique

rows donne au champ sa hauteur de départ, et par défaut sa hauteur tout court. autoGrow laisse la boîte grandir à mesure que le texte est saisi, en CSS pur.

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

const text =
  'Both fields start two rows tall.\nAdd a line to each of them.\nThe first one scrolls, the second one gets taller.'

const fixed = ref(text)
const growing = ref(text)
</script>

<template>
  <VTextarea v-model="fixed" label="Fixed height" :rows="2" />
  <VTextarea v-model="growing" label="Grows with the text" :rows="2" auto-grow />
</template>

États

invalid sert à une règle que le navigateur ne peut pas vérifier lui-même. disabled grise le champ par les tokens de couleur. readonly reste focalisable et copiable, et masque la croix. loading place un indicateur là où va l'icône de fin, le champ restant utilisable.

vue

Say a little more than that.

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

const invalid = ref('Too short')
const disabled = ref('Waiting on the form to be submitted')
const readonly = ref('Signed off on 12 March, and no longer open to changes')
const loading = ref('Writing a summary')
</script>

<template>
  <VTextarea
    v-model="invalid"
    label="Invalid"
    hint="Say a little more than that."
    invalid
    :rows="2"
  />
  <VTextarea v-model="disabled" label="Disabled" disabled :rows="2" />
  <VTextarea v-model="readonly" label="Read only" readonly :rows="2" />
  <VTextarea v-model="loading" label="Loading" loading :rows="2" />
</template>

API

Props

PropTypeDéfaut
sizeTextareaSize'sm' | 'md' | 'lg''md'
La taille du champ, qui fixe son rembourrage, son échelle typographique et ses icônes.
compactbooleanfalse
Retire 4px au champ en resserrant son rembourrage, en laissant le nombre de lignes, la typographie et les icônes tels quels.
rowsnumber5
Combien de lignes de texte le champ affiche, l'attribut natif rows, qui est ce qui donne sa hauteur au champ. Tout ce qui est sous 1 est ramené à 1, et à 1 le champ fait exactement la hauteur d'un VInput de même taille.
autoGrowbooleanfalse
Laisse le champ grandir à mesure que le texte est saisi, au lieu de défiler dans la hauteur que rows lui donne, qui reste sa hauteur de départ. C'est du CSS pur : là où le navigateur ne le prend pas en charge, le champ se comporte comme une zone de texte ordinaire.
invalidbooleanfalse
Marque le champ comme invalide quoi qu'en pense le navigateur, la voie pour une règle que seul le serveur peut vérifier.
disabledbooleanfalse
Rend le champ inutilisable, grisé par les tokens de couleur.
readonlybooleanfalse
Montre le texte sans permettre de le changer. Le champ peut toujours être focalisé et copié, et le bouton d'effacement est masqué.
labelstringaucune
Le libellé au-dessus du champ, lié à lui pour qu'un clic dessus y place le focus.
hintstringaucune
Une ligne d'aide sous le champ, liée à la zone de texte pour les technologies d'assistance afin d'être lue avec le libellé.
iconStartIconSourceaucune
Une icône dans le champ, au début. Elle est décorative jusqu'à ce qu'un écouteur @click:icon-start soit attaché : elle devient alors un vrai bouton et demande iconStartLabel.
iconEndIconSourceaucune
La même chose à la fin du champ. Le slot #end la remplace, et l'indicateur de chargement prend sa place pendant qu'il tourne.
iconStartLabelstringaucune
Ce que fait l'icône de début, en mots, une fois qu'elle est cliquable.
iconEndLabelstringaucune
Ce que fait l'icône de fin, en mots, une fois qu'elle est cliquable.
loadingbooleanfalse
Affiche un indicateur à la fin du champ, à la place de l'icône ou du slot de fin.
loadingTextstringaucune
Ce que les lecteurs d'écran annoncent pendant que l'indicateur tourne. Il retombe sur le dictionnaire du design system.
clearablebooleanfalse
Propose une croix qui vide le champ. Elle apparaît quand il y a quelque chose à effacer et que le champ est modifiable.
clearVisiblebooleanaucune
Décide si la croix est affichée, au lieu de laisser le champ le déduire de son propre contenu, champ en lecture seule compris. C'est la même échappatoire que celle de VInput, pour les composants bâtis dessus qui tiennent ailleurs que dans le texte ce qu'il y a à effacer.
clearLabelstringaucune
Ce que fait le bouton d'effacement, en mots. Il retombe sur le dictionnaire du design system.
maxlengthnumberaucune
Le nombre maximum de caractères. Par défaut c'est la limite du navigateur lui-même, qui refuse simplement tout ce qui la dépasse.
softLimitbooleanfalse
Transforme cette limite en limite souple : le lecteur peut taper au-delà, et le champ passe en erreur au lieu de refuser les frappes en silence. C'est rapporté par la validité native, donc un formulaire ne peut pas être envoyé au-dessus de la limite.
counterbooleanfalse
Affiche ce qui a été saisi, sous le champ : 12/80 face à une limite, ou simplement 12 sans limite.
v-modelstring''
Le texte du champ, vide au départ.

Événements

ÉvénementType
click:icon-start[event: MouseEvent]
L'icône de début a été pressée. Attacher cet écouteur est ce qui en fait un bouton.
click:icon-end[event: MouseEvent]
L'icône de fin a été pressée. Attacher cet écouteur est ce qui en fait un bouton.
clear[]
Le bouton d'effacement a été pressé. La valeur est déjà vidée.

Slots

SlotType
start{}
Du contenu au début du champ, rendu après iconStart plutôt qu'à sa place.
end{}
Du contenu à la fin du champ, qui remplace iconEnd. Il est masqué pendant le chargement, l'indicateur prenant cette place.
value-end{}
Des contrôles à vous à l'intérieur du champ, placés avant ceux que le champ possède : la croix d'effacement et l'icône qui ouvre le panneau. Ces deux-là sont l'affordance propre du composant, ce qui explique l'absence de slot end ici.

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