Des notifications levées depuis n'importe où dans le code en appelant toast(), et affichées par un seul VToaster monté une fois. Plusieurs peuvent s'empiler, chacune avec son propre compte à rebours.
Utilisation
vue
<script setup lang="ts">
import { VButton, toast } from 'vectis-ui'
</script>
<template>
<!-- `toast()` can be called from anywhere: a component, a store, the handler that
just saved something. What shows it is a single <VToaster /> mounted once at the
root of the application, and only one, since the queue behind these calls has a
single renderer. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'success', message: 'Changes saved.' })"
>
Save
</VButton>
</template>
Exemples
Variantes et tonalités
tone dit ce que signifie la notification, en cinq valeurs, et décide de l'icône qu'elle prend quand aucune n'est donnée. variant est l'intensité avec laquelle ce ton est peint, teinté ou plein.
vue
soft, the default
solid
<script setup lang="ts">
import { VButton, toast, type ToastTone } from 'vectis-ui'
const tones: ToastTone[] = ['neutral', 'accent', 'success', 'warning', 'danger']
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- The tone says what the notification means, and it also decides which icon it
takes when none is given. Five of them, because a notification reports a state
and success and warning are states. -->
<div class="row">
<p class="caption">soft, the default</p>
<div class="buttons">
<VButton
v-for="tone in tones"
:key="tone"
variant="outline"
tone="neutral"
@click="toast({ tone, message: `A ${tone} notification.` })"
>
{{ tone }}
</VButton>
</div>
</div>
<!-- The variant is how strongly it is painted: a tinted background with a border,
or the full colour. -->
<div class="row">
<p class="caption">solid</p>
<div class="buttons">
<VButton
v-for="tone in tones"
:key="tone"
variant="outline"
tone="neutral"
@click="toast({ tone, variant: 'solid', message: `A solid ${tone} notification.` })"
>
{{ tone }}
</VButton>
</div>
</div>
</div>
</template>
<style scoped>
.demo {
display: grid;
gap: var(--vectis-space-5);
}
.row {
display: grid;
gap: var(--vectis-space-2);
}
.buttons {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
.caption {
margin: 0;
color: var(--vectis-color-text-muted);
font-size: var(--vectis-text-caption-size);
}
</style>
Titre et message
message porte la notification, et title l'encadre en quelques mots quand le message seul ne dirait pas de quoi il retourne.
vue
<script setup lang="ts">
import { VButton, toast } from 'vectis-ui'
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- The message is the whole of it, and one sentence is usually enough. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'success', message: 'Changes saved.' })"
>
Message only
</VButton>
<!-- A title frames the message when the message alone would not say what it is
about. Keep it to a few words: it is a heading, not a first sentence. -->
<VButton
variant="outline"
tone="neutral"
@click="
toast({
tone: 'danger',
title: 'Upload failed',
message: 'invoice-2481.pdf is larger than the 10 MB limit.',
})
"
>
Title and message
</VButton>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
</style>
Icônes
Sans elle, icon vient du ton. En nommer une la remplace, et passer false la retire tout à fait.
vue
<script setup lang="ts">
import { VButton, toast } from 'vectis-ui'
import { cloud_upload as cloudUpload } from 'vectis-ui/icons'
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- Left out, the icon comes from the tone: a notification arrives unannounced, so
it is scanned before it is read and the glyph is what carries the meaning at a
glance. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'warning', message: 'Your session expires in 5 minutes.' })"
>
From the tone
</VButton>
<!-- Name one and it replaces the tone's, for a notification whose subject is more
specific than its meaning. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'success', icon: cloudUpload, message: 'Backup finished.' })"
>
A custom icon
</VButton>
<!-- `false` removes it altogether, which is not the same as leaving it out: the
card then carries no glyph at all and the text runs to the edge. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'accent', icon: false, message: 'Three new comments.' })"
>
No icon
</VButton>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
</style>
Largeur
width accepte n'importe quelle longueur CSS et remplace le plancher et le plafond de la carte. Elle ne dépasse jamais la largeur de la fenêtre.
vue
<script setup lang="ts">
import { VButton, toast } from 'vectis-ui'
const LONG =
'The export finished with 3 warnings. Rows 12, 48 and 91 were skipped because their reference column was empty.'
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- Left alone the card sits between a floor and a ceiling of its own, so a short
message is not a sliver and a long one does not stretch across the page. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'warning', title: 'Export finished', message: LONG })"
>
Default width
</VButton>
<!-- Any CSS length replaces both. It is never allowed past the width of the
viewport, margins included, so a value too large for a phone is simply
ignored there rather than pushing the card off the screen. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'warning', title: 'Export finished', message: LONG, width: '32rem' })"
>
32rem
</VButton>
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'accent', message: 'Saved.', width: '14rem' })"
>
14rem
</VButton>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
</style>
Placements
placement pose la notification dans l'un des six coins, chacun ayant sa propre pile. Posé sur le VToaster, il est la valeur par défaut de toutes les notifications ; passé au moment d'en lever une, il n'appartient qu'à elle.
vue
<script setup lang="ts">
import { VButton, toast, type ToastPlacement } from 'vectis-ui'
const placements: ToastPlacement[] = [
'top-left',
'top-center',
'top-right',
'bottom-left',
'bottom-center',
'bottom-right',
]
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- Six corners, each with a stack of its own, so notifications aimed at different
ones never queue behind each other. Set on the VToaster the placement is the
default for every notification; passed here it is this one's alone. -->
<VButton
v-for="placement in placements"
:key="placement"
variant="outline"
tone="neutral"
@click="toast({ placement, message: `Raised at ${placement}.` })"
>
{{ placement }}
</VButton>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
</style>
Empilement
Les notifications s'empilent au lieu de se remplacer, chacune gardant son propre compte à rebours, si bien qu'elles partent au rythme de leur propre horloge.
vue
<script setup lang="ts">
import { VButton, toast } from 'vectis-ui'
let n = 0
function raise() {
n += 1
toast({ tone: 'accent', message: `Notification ${n}.` })
}
function raiseThree() {
toast({ tone: 'success', message: 'Backup finished.' })
toast({ tone: 'warning', message: 'Two files were skipped.' })
toast({ tone: 'danger', message: 'The report could not be sent.' })
}
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- Notifications stack rather than replace one another, because two states can be
true at the same time: a finished backup and a failed send are both worth
reading. Each keeps a countdown of its own, so they go away in the order their
own clocks run out and not in the order they arrived. -->
<VButton variant="outline" tone="neutral" @click="raise">Raise one more</VButton>
<VButton variant="outline" tone="neutral" @click="raiseThree">Raise three at once</VButton>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
</style>
Combien de temps elle reste
duration est la durée d'affichage d'une notification, cinq secondes par défaut, et chacune peut demander la sienne. Le compte à rebours se suspend tant que le pointeur repose quelque part sur la pile et tant que le clavier y est, et ne repart que lorsque les deux sont partis.
vue
<script setup lang="ts">
import { VButton, toast } from 'vectis-ui'
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- Five seconds by default, and every notification may ask for its own. The
countdown holds while the pointer rests anywhere on the stack, so something
that disappears on a clock can be read to the end. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'accent', message: 'Gone in 2 seconds.', duration: 2000 })"
>
2 seconds
</VButton>
<VButton
variant="outline"
tone="neutral"
@click="
toast({
tone: 'warning',
title: 'Take your time',
message: 'Gone in 10 seconds, unless the pointer rests on it.',
duration: 10000,
})
"
>
10 seconds
</VButton>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
</style>
Notifications persistantes
Une duration de 0 désarme le compte à rebours et la notification reste jusqu'à ce qu'on la retire. Laissez la croix de fermeture pour qu'il y ait une sortie.
vue
<script setup lang="ts">
import { VButton, toast } from 'vectis-ui'
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<!-- A duration of 0 disarms the countdown: the notification then stays until it is
dismissed. Reserve it for something the reader has to see, a failure they can
act on, and leave the close cross on so there is a way out. -->
<VButton
variant="outline"
tone="neutral"
@click="
toast({
tone: 'danger',
title: 'Connection lost',
message: 'Your changes are kept locally until the connection comes back.',
duration: 0,
})
"
>
Stays until dismissed
</VButton>
</template>
Renvoyer une notification
hideClose retire la croix de fermeture. toast rend un identifiant et dismissToast retire cette notification, ou toutes d'un coup lorsqu'il est appelé sans argument.
vue
<script setup lang="ts">
import { ref } from 'vue'
import { VButton, dismissToast, toast } from 'vectis-ui'
const id = ref<number | null>(null)
function raise() {
// `toast` hands back an id, which is what lets this notification be taken away from
// code: the request it was about came back, or the state it reported is over.
id.value = toast({ tone: 'accent', message: 'Uploading…', duration: 0 })
}
function dismissOne() {
if (id.value !== null) dismissToast(id.value)
id.value = null
}
</script>
<template>
<!-- Raised into the <VToaster /> mounted once at the root of the application. -->
<div class="demo">
<!-- The close cross is on by default, and turning it off only makes sense on a
notification that goes away on its own: with no countdown and no cross,
nothing but code can remove it. -->
<VButton
variant="outline"
tone="neutral"
@click="toast({ tone: 'success', message: 'Saved.', hideClose: true })"
>
No cross
</VButton>
<VButton variant="outline" tone="neutral" @click="raise">Raise one to dismiss</VButton>
<VButton variant="outline" tone="neutral" @click="dismissOne">Dismiss that one</VButton>
<!-- With no argument it clears every notification at once. -->
<VButton variant="outline" tone="neutral" @click="dismissToast()">Dismiss all</VButton>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-wrap: wrap;
gap: var(--vectis-space-3);
}
</style>
Dans quel coin les notifications apparaissent, sauf si l'une d'elles en demande un autre.
duration
number
5000
Combien de temps une notification reste, en millisecondes, sauf si elle demande autre chose. Une notification à qui l'on donne 0 reste jusqu'à ce qu'elle soit fermée.
closeLabel
string
aucune
Ce que fait la croix de fermeture, en mots. Elle retombe sur le dictionnaire du design system.
label
string
aucune
Ce que les lecteurs d'écran annoncent pour les zones de notification elles-mêmes, qui sont des points de repère de la page. Il retombe sur le dictionnaire du design system.