Toast
Una notificación flotante que se desliza para descartar: sigue al dedo y solo se va al soltar.
Instalación
$ pnpm dlx shadcn@latest add @ssntl/toastUso
import { Toast, ToastAction, ToastDescription, ToastProvider, ToastTitle, ToastViewport } from "@/components/ui/toast"
<ToastProvider swipeDirection="right" label="Notificación">
<Toast open={open} onOpenChange={setOpen} closeLabel="Descartar">
<ToastTitle>Pedido archivado</ToastTitle>
<ToastDescription>Pasó a Archivo con su historial.</ToastDescription>
<ToastAction altText="Abre Archivo para restaurarlo">Deshacer</ToastAction>
</Toast>
<ToastViewport />
</ToastProvider>Reglas
Lo que este componente espera de ti, tal como se instala en components/ui/toast.md junto al código. El archivo completo agrega cuándo usarlo, teclado, los fundamentos de UI que aplica y cada regla compartida (en inglés).
## Reglas de Toast
- **Notificación flotante.** Elevation-4, sobre la página y sus menús; se anuncia con cortesía, se pausa al pasar el cursor o con foco y se alcanza con F8.
- **Gesto inmediato.** El toast sigue al dedo 1:1 desde el primer píxel.
- **Gesto continuo.** El puntero sigue capturado aunque salga del toast.
- **Gesto cancelable.** Se descarta al soltar pasado el umbral; si sueltas antes, regresa.
- Como máximo una acción, con `altText` para quien no alcance el toast a tiempo.
- Con una acción o un error queda hasta que se descarte (duration={Infinity}); una confirmación simple dura al menos 5 segundos.
- El botón de cierre dice “Dismiss notification” por defecto; cambia `closeLabel` en otros idiomas.Código
"use client"
import * as React from "react"
import { Toast as ToastPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
import { CloseButton } from "@/registry/ssntl/ui/close-button"
// A floating notification (Radix Toast): announced politely, paused while
// hovered or focused, and reachable with F8. Floating notification:
// elevation 4, above the page and its menus.
// Gestures: swipe right to dismiss. The toast follows the finger 1:1 from
// the first pixel (responsive), keeps the pointer even off the toast
// (continuous) and only dismisses on release past the threshold; letting go
// short of it springs back (cancelable).
const ToastProvider = ToastPrimitive.Provider
function ToastViewport({
className,
...props
}: React.ComponentProps<typeof ToastPrimitive.Viewport>) {
return (
<ToastPrimitive.Viewport
data-slot="toast-viewport"
className={cn(
"fixed inset-x-4 bottom-4 z-50 mx-auto grid max-w-sm gap-2 outline-none",
className
)}
{...props}
/>
)
}
function Toast({
className,
children,
closeLabel = "Dismiss notification",
...props
}: React.ComponentProps<typeof ToastPrimitive.Root> & {
/** The close button's accessible name. */
closeLabel?: string
}) {
return (
<ToastPrimitive.Root
data-slot="toast"
className={cn(
"relative grid touch-pan-y gap-1 rounded-lg bg-popover p-5 pe-16 text-left text-popover-foreground elevation-4 select-none",
"data-[state=closed]:pop-out data-[state=open]:pop-in",
"data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=move]:transition-none",
"data-[swipe=cancel]:translate-x-0 data-[swipe=cancel]:transition-[translate] data-[swipe=cancel]:duration-(--duration-menu) data-[swipe=cancel]:ease-out",
"data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=end]:pop-out",
className
)}
{...props}
>
{children}
<ToastPrimitive.Close asChild>
<CloseButton label={closeLabel} className="absolute end-2 top-2" />
</ToastPrimitive.Close>
</ToastPrimitive.Root>
)
}
function ToastTitle({
className,
...props
}: React.ComponentProps<typeof ToastPrimitive.Title>) {
return (
<ToastPrimitive.Title
data-slot="toast-title"
className={cn("text-label", className)}
{...props}
/>
)
}
function ToastDescription({
className,
...props
}: React.ComponentProps<typeof ToastPrimitive.Description>) {
return (
<ToastPrimitive.Description
data-slot="toast-description"
className={cn(
"text-caption text-pretty text-muted-foreground",
className
)}
{...props}
/>
)
}
/** One follow-up action, such as Undo; altText says how to do it otherwise. */
function ToastAction({
className,
...props
}: React.ComponentProps<typeof ToastPrimitive.Action>) {
return (
<ToastPrimitive.Action
data-slot="toast-action"
className={cn(
"mt-2 inline-flex h-9 w-fit cursor-pointer items-center rounded-full bg-secondary px-4 text-caption font-medium",
"transition-[background-color,scale] duration-(--duration-fast) ease-out hover:bg-neutral-200 active:scale-(--es-press) motion-reduce:active:scale-100 dark:hover:bg-neutral-600",
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
className
)}
{...props}
/>
)
}
export {
Toast,
ToastAction,
ToastDescription,
ToastProvider,
ToastTitle,
ToastViewport,
}