Toasts
Notifications client, provider, hook useToast et conteneur à monter dans le layout.
core/toast fournit les notifications éphémères de l'interface, sur un contexte React. Il expose un provider, un hook et un conteneur.
Règle absolue : un seul système de toast dans toute l'application. Ne pas ajouter de bibliothèque concurrente ni de notification maison.
Import
import { ToastProvider, useToast, ToastContainer, Toast } from '@lrvo/core/toast';Module client. Il est client-safe et importable depuis un fichier 'use client'.
Mise en place
Le plus simple est de monter LrvoProvider, qui inclut déjà le provider et le conteneur. Le câblage manuel reste possible :
import { ToastProvider, ToastContainer } from '@lrvo/core/toast';
export default function RootLayout({ children }) {
return (
<ToastProvider>
{children}
<ToastContainer />
</ToastProvider>
);
}useToast lève si on l'appelle hors du ToastProvider.
API
useToast()
const { success, error, warning, info, addToast, removeToast, clearAllToasts } = useToast();L'objet retourné a une identité stable pour toute la durée de vie de l'application. Il peut donc figurer sans précaution dans les dépendances d'un useCallback ou d'un useEffect.
const toast = useToast();
const load = useCallback(async () => {
setLoading(true);
try {
setItems(await api('/admin/items'));
} catch (err) {
toast.error(err.message);
} finally {
setLoading(false);
}
}, [toast]);
useEffect(() => { load(); }, [load]);C'est le motif attendu dans toutes les pages de liste de l'admin. Le provider sépare les actions de la liste des toasts : afficher une notification ne change que la seconde, et seul ToastContainer s'y abonne. Sans cette séparation, chaque toast affiché relancerait load, une fois à l'apparition, une fois au marquage de sortie et une fois au retrait.
Raccourcis par type :
success('Modifications enregistrées.');
error('La connexion a échoué.');
warning('Session sur le point d\'expirer.');
info('Une mise à jour est disponible.');Chacun accepte un objet d'options en second argument et retourne l'identifiant du toast créé.
success('Fichier importé.', { duration: 3000, dismissible: false });addToast(toast)
Crée un toast à partir d'un objet complet.
const id = addToast({
type: 'success',
message: 'Profil mis à jour.',
title: 'Enregistré',
duration: 4000,
dismissible: true,
});| Paramètre | Type | Défaut | Rôle |
|---|---|---|---|
type | 'success' | 'error' | 'warning' | 'info' | 'info' | Variante visuelle. |
message | string | — | Corps du toast. |
title | string | selon type | Titre. Sans valeur : « Succès », « Erreur », « Avertissement », « Information ». |
duration | number | 5000 | Millisecondes avant disparition. 0 désactive la disparition automatique. |
dismissible | boolean | true | Affiche le bouton de fermeture. |
Durées par défaut : error 7000 ms, warning 6000 ms, success et info 5000 ms.
removeToast(id) et clearAllToasts()
Retirent un toast, ou tous.
ToastContainer
À monter une seule fois. Affiche les toasts en bas à droite, empilés. Au survol du plus récent, la pile se déploie à taille réelle.
<ToastContainer maxToasts={5} />| Prop | Type | Défaut | Rôle |
|---|---|---|---|
maxToasts | number | 5 | Nombre de toasts visibles simultanément. |
Rédaction des messages
Un toast rapporte ce qui s'est passé, au passé passif, sans « avec succès » et sans « vous ».
success('Page enregistrée.'); // ✓
success('Vos modifications ont été enregistrées avec succès !'); // ✗Voir Rédaction.
Notes
Pas de toast depuis un composant serveur. Le hook vit dans le bundle client. Une mutation faite en server action retourne un résultat que le composant client transforme en toast.
La liste brute des toasts n'est pas exposée. Afficher la pile est le travail de ToastContainer, qui lit un contexte interne au module. Un appelant qui lirait useToast().toasts reçoit encore la valeur courante, mais cette lecture ne déclenche aucun rendu et disparaîtra à la prochaine version majeure.
Les minuteries sont annulées au démontage du provider. Retirer un toast à la main annule aussi la disparition automatique qui lui restait programmée.