CommunityImagegithub.com

RevanthThota55/FreeFrame-Studio

Guide pour Sonner, la bibliothèque de toasts React — installation et configuration du Toaster, choix du bon appel toast(), toasts de promesse et de chargement, mise à jour, suppression et persistance des toasts, style, thèmes et icônes, positionnement et toasters multiples. À utiliser lorsque vous travaillez avec Sonner ou que vous le dépannez — toasts qui n'apparaissent pas, apparaissent deux fois, perdent leur style, ignorent les classes Tailwind, se retrouvent derrière une modale ou ne suivent pas le mode sombre.

Qu'est-ce que FreeFrame-Studio ?

Ce guide de compétence dédié à Sonner, la bibliothèque de toasts React, fournit une référence complète pour l'installation, le style et le dépannage. Il exploite la connaissance de l'auteur original, Emil Kowalski, et couvre un large éventail de fonctionnalités : du montage unique du composant `<Toaster />` dans un layout à l'utilisation des différents appels de la fonction `toast()` (message simple, succès, erreur, chargement, promesse, JSX personnalisé). Le guide introduit une 'échelle d'escalade' pour le style, allant des valeurs par défaut et ajustements simples jusqu'à la méthode headless sans style, en passant par les classes CSS. Il inclut un tableau de dépannage complet qui traite les symptômes courants comme les toasts qui n'apparaissent pas, les doublons, les conflits de style avec Tailwind, les problèmes d'affichage dans l'ombre DOM et les interférences avec les modales. La compétence est conçue pour aider les développeurs à intégrer et personnaliser efficacement Sonner sur différentes plateformes comme Next.js, React et Astro.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/RevanthThota55/FreeFrame-Studio/tree/HEAD/.claude/skills/ask-sonner

Installed? Explore more Image skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Travailler avec Sonner

Réponse initiale

Lorsque cette compétence est invoquée pour la première fois sans question spécifique, répondez uniquement avec :

Je suis prêt à vous aider à configurer, styliser et dépanner Sonner, mes connaissances proviennent de son auteur, Emil Kowalski.

Ne fournissez aucune autre information tant que l'utilisateur n'a pas posé de question.

Un guide de compétence pour Sonner, la bibliothèque de toasts. Lorsqu'une tâche implique Sonner — le configurer, afficher des toasts, les styliser ou les réparer — répondez d'abord à partir de ce fichier. Les tableaux de propriétés complets pour <Toaster /> et toast() se trouvent dans API.md ; lisez-le lorsque vous avez besoin d'un nom de propriété, d'un type ou d'une valeur par défaut exacts.

Configuration

Deux éléments, et seulement deux :

  1. Un <Toaster />, monté une fois, aussi près de la racine que possible (dans Next.js : layout.tsx — il fonctionne à l'intérieur des composants serveur). Ne le rendez jamais par page ou de manière conditionnelle ; un deuxième Toaster monté duplique chaque toast.
  2. toast() appelé depuis le code client — gestionnaires d'événements, effets, callbacks. C'est une simple fonction, pas besoin de hook ou de fournisseur, mais elle ne fait rien côté serveur : dans une action serveur, retournez le résultat et appelez toast() dans le code client qui le reçoit.
import { Toaster } from 'sonner'; // une fois, dans layout
import { toast } from 'sonner';   // n'importe où côté client

Choisir le bon appel

Vous voulezAppel
Message simpletoast('Titre') — ajoutez { description } pour une deuxième ligne
Icône succès / erreur / info / avertissementtoast.success('…'), toast.error('…'), etc.
Spinner pendant que vous gérez l'état vous-mêmetoast.loading('…'), puis mettez-le à jour par son id
Chargement → succès/erreur lié à une promessetoast.promise(promise, { loading, success, error }) — success/error acceptent des fonctions recevant la valeur résolue / l'erreur
Bouton qui fait quelque chose{ action: { label, onClick } } — ferme le toast à moins que onClick n'appelle event.preventDefault() ; cancel est la variante secondaire
JSX personnalisé, coque de toast par défauttoast(<jsx />)
JSX personnalisé, sans aucun styletoast.custom((t) => <jsx />) — headless, t vous donne l'id pour le supprimer

Recettes

Mettre à jour un toast — appelez toast() à nouveau avec le même id ; seules les propriétés que vous passez changent. Passer à toast.success(…, { id }) change le type. C'est ainsi que fonctionnent les flux chargement → succès sans toast.promise :

const id = toast.loading('Téléchargement…');
toast.success('Téléchargé', { id });

Persister — { duration: Infinity }. Supprimer — toast.dismiss(id), ou toast.dismiss() pour tous. Lire les toasts actifs — useSonner() dans React, toast.getActiveToasts() en dehors.

Liens ou composants dans le texte — passez une fonction pour le titre ou la description : toast(() => <a href="…">Voir</a>).

Toasters multiples — donnez à chacun un id et ciblez avec toast('…', { toasterId: 'canvas' }). Sans toasterId, chaque toaster affiche le toast.

Callbacks de fermeture — onDismiss se déclenche sur le bouton de fermeture ou le balayage ; onAutoClose se déclenche sur expiration du délai. Ils sont séparés ; il n'existe pas de callback unique « fermé ».

Style — l'échelle d'escalade

Ne montez que selon ce que le changement nécessite ; sauter trop tôt à l'échelon supérieur est acceptable (c'est l'état final recommandé), s'attarder au milieu ne l'est pas.

  1. Valeurs par défaut — plus richColors sur le Toaster pour des couleurs vives en succès/erreur, invert pour inverser selon le thème.
  2. Ajustements en ligne — toastOptions={{ style: {…} }} sur le Toaster pour tous les toasts, ou style par appel toast().
  3. Classes sur les parties — toastOptions={{ classNames: { toast, title, description, actionButton, cancelButton, closeButton } }}. Les styles injectés par Sonner gagnent la cascade, donc chaque classe a besoin de !important (Tailwind : !text-red-900). Si vous marquez plus de quelques éléments important, arrêtez — passez en headless.
  4. Headless — toast.custom() avec votre propre JSX, en conservant le positionnement, l'empilement et le balayage de Sonner. L'approche recommandée pour un toast de système de design : enveloppez-le dans votre propre abstraction toast(). (unstyled: true existe comme solution intermédiaire, mais headless offre plus de contrôle pour le même effort.)

Icônes — remplacez les valeurs par défaut par type avec la propriété icons du Toaster, par toast avec icon, supprimez avec null.

Thème — theme par défaut à 'light' et ne suit pas l'OS. Passez theme="system", ou connectez votre fournisseur de thème : <Toaster theme={resolvedTheme} /> depuis next-themes.

Dépannage

SymptômeCause → correctif
Le toast n'apparaît jamaisAucun <Toaster /> monté, ou il a été démonté (rendu conditionnel, placement par page). Montez-en un à la racine. Si appelé depuis une action serveur : toast() est côté client uniquement — appelez-le avec le résultat de l'action sur le client.
Le même toast apparaît deux foisDeux Toasters montés (layout et page) — gardez-en un. Ou toast() déclenché dans un effet sous la double invocation de développement de React StrictMode — déclenchez-le depuis le gestionnaire d'événements à la place, ou passez un id stable pour que le deuxième appel mette à jour plutôt que duplique.
Les classes Tailwind/CSS n'ont aucun effetLes styles par défaut les écrasent. Marquez-les !important, ou utilisez unstyled / headless (voir l'échelle ci-dessus).
Les toasts s'affichent complètement sans style (courant dans Astro, transitions de vue)La feuille de style injectée par Sonner a été perdue — importez-la explicitement dans un layout : import 'sonner/dist/styles.css'.
Sans style dans Shadow DOMLes styles atterrissent dans document.head, pas dans la racine fantôme. Copiez la balise style dont le texte inclut [data-sonner-toaster] dans la racine fantôme.
Toast derrière une modale / superposition, ou rognéUn ancêtre crée un contexte d'empilement (transform, filter, overflow) ou la superposition a un indice z supérieur au toaster. Déplacez <Toaster /> à la racine du document, en dehors de tout conteneur de boîte de dialogue / portail.
Mode sombre ignorétheme par défaut à 'light' — définissez theme="system" ou passez le thème résolu (voir Thème ci-dessus).
Succès/erreur semblent gris, pas vert/rougeC'est la valeur par défaut. Ajoutez richColors au Toaster.
Le toast ne se ferme jamaisduration: Infinity, dismissible: false, ou une toast.promise dont la promesse ne se règle jamais — le toast de chargement attend indéfiniment.
toast.promise bloqué sur chargementIl a besoin d'une promesse (ou d'une fonction en retournant une) comme premier argument, et la promesse doit effectivement se résoudre / échouer.
Le balayage pour supprimer va dans la mauvaise direction / ne fonctionne pasLes directions dérivent de position. Remplacez avec swipeDirections sur le Toaster.
Le toast apparaît dans chaque toasterLes toasters multiples nécessitent un ciblage : donnez à chaque Toaster un id et passez toasterId dans l'appel toast().
Toasts trop près du bord de l'écran sur mobileoffset (bureau, par défaut 32px) et mobileOffset (<600px, par défaut 16px) — nombres, chaînes CSS, ou objets par côté.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

RevanthThota55/FreeFrame-Studio

Build an animation from scratch, making the decisions in the order that determines whether it feels right — should it animate at all, what purpose, which tool, which properties, which curve and duration, how it interrupts, how it exits. Writes the implementation. Use when asked to animate something, add motion, make a component feel alive, or build a transition. For critiquing existing motion use review-animations; for auditing a whole codebase use improve-animations.

RevanthThota55/FreeFrame-Studio

Keep web animations inside the frame budget — animate composite-only properties, keep motion off the main thread when the page is busy, and find the cause when an animation drops frames. Covers the layout/paint/composite pipeline, cheaper property swaps, CSS vs WAAPI vs requestAnimationFrame, Framer Motion's hardware-accelerated path, React re-rendering per frame, inherited CSS variable recalculation, blur cost, and when `will-change` actually helps. Use when an animation is janky, choppy, stutters, or drops frames; when choosing which property to animate; when deciding between CSS and JS animation on performance grounds; or when reaching for `will-change` or GPU layers. For choosing easing, duration, or whether to animate at all use animate; for reviewing motion as a whole use review-animations.

RevanthThota55/FreeFrame-Studio

Reverse-lookup glossary that turns a vague description of a web animation or motion effect into its exact term ("the bouncy thing when a popover opens" → Pop in; "the iOS rubber-band scroll" → Rubber-banding). Use when the user asks "what's it called when…", or describes a motion effect without knowing its name and wants the right word to prompt an AI or designer with. For naming an effect, not designing or building one.

RevanthThota55/FreeFrame-Studio

Apple's approach to interface design and fluid, physical motion, translated for the web. Use when building or reviewing gesture-driven UI, spring animations, drag/swipe/sheet interactions, momentum and interruptible transitions, translucent materials and depth, typography (optical sizing, tracking, leading), reduced-motion, or the design foundations (feedback, spatial consistency, restraint) behind Apple-style interfaces.

Skills associés