CommunityImagengithub.com

RevantThota55/FreeFrame-Studio

Guía sobre Sonner, la librería React para toasts: instala y configura el Toaster, elige la llamada toast() adecuada, toasts con promesas y de carga, actualización, descarte y persistencia, estilos, temas e íconos, posicionamiento y múltiples toasters. Úsalo al trabajar con Sonner o solucionar problemas como toasts que no aparecen, aparecen dos veces, pierden estilos, ignoran clases de Tailwind, quedan detrás de un modal o no siguen el modo oscuro.

¿Qué es FreeFrame-Studio?

Esta habilidad es una guía completa para Sonner, la popular librería de toasts para React. Cubre desde la instalación inicial y configuración del componente `<Toaster />` hasta técnicas avanzadas de personalización y resolución de problemas comunes. La guía está estructurada para ayudar tanto a quienes comienzan como a quienes ya trabajan con Sonner y necesitan depurar comportamientos inesperados. Explica detalladamente cómo usar los diferentes tipos de toasts (`success`, `error`, `loading`, `promise`), cómo actualizar y descartar toasts mediante su ID, y cómo manejar múltiples toasters. Además, incluye una sección de estilos escalonada que va desde los valores predeterminados hasta el uso de clases con `!important` y la creación de toasts completamente personalizados con `toast.custom()`. La guía también cubre temas cruciales como la integración con temas del sistema, la importación de estilos en entornos como Astro, y la solución de problemas dentro de Shadow DOM o cuando los toasts quedan detrás de modales. Está escrita para desarrolladores que usan React, Next.js o Astro, y se basa en la documentación oficial de Sonner y el conocimiento de su autor, Emil Kowalski. La habilidad responde preguntas específicas y proporciona soluciones prácticas para que los toasts funcionen correctamente en cualquier proyecto.

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

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Trabajando con Sonner

Respuesta Inicial

Cuando se invoque esta habilidad por primera vez sin una pregunta específica, responde únicamente con:

Estoy listo para ayudarte a configurar, estilizar y solucionar problemas con Sonner. Mi conocimiento proviene de su autor, Emil Kowalski.

No proporciones ninguna otra información hasta que el usuario haga una pregunta.

Una guía de habilidad para Sonner, la librería de toasts. Cuando una tarea involucre Sonner (configurarlo, renderizar toasts, estilizarlos o arreglarlos), responde primero desde este archivo. Las tablas completas de propiedades para <Toaster /> y toast() están en API.md; léelo cuando necesites un nombre de propiedad, tipo o valor predeterminado exacto.

Configuración

Dos piezas, y solo dos:

  1. Un <Toaster />, montado una vez, lo más cerca posible de la raíz (en Next.js: layout.tsx — funciona dentro de componentes servidor). Nunca lo renderices por página o condicionalmente; un segundo Toaster montado duplica cada toast.
  2. toast() llamado desde código cliente — manejadores de eventos, efectos, callbacks. Es una función simple, no necesita hook ni provider, pero no hace nada en el servidor: en una action del servidor, devuelve el resultado y llama a toast() en el código cliente que lo recibe.
import { Toaster } from 'sonner'; // una vez, en el layout
import { toast } from 'sonner';   // en cualquier lugar del lado cliente

Elegir la llamada correcta

QuieresLlama
Mensaje simpletoast('Título') — añade { description } para una segunda línea
Icono de éxito / error / info / advertenciatoast.success('…'), toast.error('…'), etc.
Spinner mientras gestionas el estado tú mismotoast.loading('…'), luego actualízalo por id
Carga → éxito/error vinculado a una promesatoast.promise(promise, { loading, success, error }) — success/error aceptan funciones que reciben el valor resuelto/error
Botón que hace algo{ action: { label, onClick } } — cierra el toast a menos que onClick llame a event.preventDefault(); cancel es la variante secundaria
JSX personalizado, con la estructura base del toasttoast(<jsx />)
JSX personalizado, sin estilostoast.custom((t) => <jsx />) — headless, t te da el id para descartar

Recetas

Actualizar un toast — vuelve a llamar a toast() con el mismo id; solo cambian las props que pases. Cambiar a toast.success(…, { id }) cambia el tipo. Así es como funcionan los flujos de carga → éxito sin toast.promise:

const id = toast.loading('Subiendo…');
toast.success('Subido', { id });

Persistir — { duration: Infinity }. Descartar — toast.dismiss(id), o toast.dismiss() para todos. Leer toasts activos — useSonner() en React, toast.getActiveToasts() fuera de él.

Enlaces o componentes en el texto — pasa una función para el título o la descripción: toast(() => <a href="…">Ver</a>).

Múltiples toasters — asigna a cada uno un id y apunta con toast('…', { toasterId: 'canvas' }). Sin toasterId, todos los toasters renderizan el toast.

Callbacks de cierre — onDismiss se dispara al hacer clic en el botón de cerrar o al deslizar; onAutoClose se dispara al expirar el tiempo. Son independientes; no hay un solo callback de "cerrado".

Estilos — la escalera de escalada

Sube solo hasta donde lo requiera el cambio; saltar al peldaño más alto demasiado pronto está bien (es el estado final recomendado), pero quedarse en el medio no.

  1. Valores predeterminados — más richColors en el Toaster para éxito/error coloridos, invert para invertir contra el tema.
  2. Ajustes en línea — toastOptions={{ style: {…} }} en el Toaster para todos los toasts, o style por llamada a toast().
  3. Clases en partes — toastOptions={{ classNames: { toast, title, description, actionButton, cancelButton, closeButton } }}. Los estilos inyectados de Sonner ganan la cascada, por lo que cada clase necesita !important (Tailwind: !text-red-900). Si estás marcando más de unas pocas cosas como importantes, detente — ve a headless.
  4. Headless — toast.custom() con tu propio JSX, manteniendo el posicionamiento, apilamiento y deslizamiento de Sonner. El enfoque recomendado para un toast de sistema de diseño: envuélvelo en tu propia abstracción toast(). (unstyled: true existe como término medio, pero headless da más control por el mismo esfuerzo.)

Íconos — intercambia los predeterminados por tipo con la prop icons del Toaster, por toast con icon, elimínalos con null.

Tema — theme por defecto es 'light' y no sigue al SO. Pasa theme="system", o conecta tu proveedor de temas: <Toaster theme={resolvedTheme} /> desde next-themes.

Solución de problemas

SíntomaCausa → solución
El toast nunca apareceNo hay <Toaster /> montado, o se desmontó (renderizado condicional, colocación por página). Monta uno en la raíz. Si se llama desde una server action: toast() es solo cliente — llámalo con el resultado de la action en el cliente.
El mismo toast aparece dos vecesDos Toasters montados (layout y página) — mantén uno. O toast() disparado en un efecto bajo la doble invocación en desarrollo de React StrictMode — dispara desde el manejador de eventos, o pasa un id estable para que la segunda llamada actualice en lugar de duplicar.
Las clases de Tailwind/CSS no tienen efectoLos estilos predeterminados los anulan. Márcalos con !important, o usa unstyled / headless (ver la escalera arriba).
Los toasts se renderizan completamente sin estilos (común en Astro, transiciones de vista)La hoja de estilos inyectada de Sonner se perdió — impórtala explícitamente en un layout: import 'sonner/dist/styles.css'.
Sin estilos dentro de Shadow DOMLos estilos caen en document.head, no en la shadow root. Copia la etiqueta de estilo cuyo texto incluya [data-sonner-toaster] dentro de la shadow root.
Toast detrás de un modal/overlay, o recortadoUn ancestro crea un contexto de apilamiento (transform, filter, overflow) o el overlay supera en z-index al toaster. Mueve <Toaster /> a la raíz del documento, fuera de cualquier contenedor de diálogo/portal.
Modo oscuro ignoradotheme por defecto es 'light' — establece theme="system" o pasa el tema resuelto (ver Tema arriba).
El éxito/error se ve gris, no verde/rojoEso es el predeterminado. Añade richColors al Toaster.
El toast nunca se cierraduration: Infinity, dismissible: false, o un toast.promise cuya promesa nunca se resuelve — el toast de carga espera para siempre.
toast.promise se queda en cargaNecesita una promesa (o una función que devuelva una) como primer argumento, y la promesa debe resolverse/rechazarse realmente.
Deslizar para descartar va en la dirección incorrecta / no funcionaLas direcciones se derivan de position. Sobrescribe con swipeDirections en el Toaster.
El toast aparece en todos los toastersMúltiples toasters necesitan direccionamiento: asigna a cada Toaster un id y pasa toasterId en la llamada a toast().
Toasts demasiado cerca del borde de la pantalla en móviloffset (escritorio, 32px por defecto) y mobileOffset (<600px, 16px por defecto) — números, cadenas CSS, u objetos por lado.

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 relacionados