Saltar al contenido principal

Toast

Feedback no intrusivo. Alertas automáticas. Confirmar éxito.

1'use client';
2
3import { Button } from '@/components/ui/button';
4import { Toast, useToast } from '@/components/ui/toast';
5
6function ToastDemo() {
7 const { toast } = useToast();
8
9 return (
10 <Button
11 variant="outline"
12 onClick={() =>
13 toast({
14 title: 'Invitation sent',
15 description: 'Lucia Mendez gets access to Acme Studio once she accepts.',
16 })
17 }
18 >
19 Invite teammate
20 </Button>
21 );
22}
23
24export function Default() {
25 return (
26 <Toast.Provider>
27 <ToastDemo />
28 </Toast.Provider>
29 );
30}

Instalación

pnpm dlx nachui add toast

Anatomía

1import { Toast, useToast } from '@/components/ui/toast';
Envolvé tu app con Toast.Provider, después usá useToast() en donde quieras:
1function App() {
2 return (
3 <Toast.Provider>
4 <MiComponente />
5 </Toast.Provider>
6 );
7}
8
9function MiComponente() {
10 const { toast } = useToast();
11
12 return <button onClick={() => toast({ title: '¡Hola!' })}>Mostrar Toast</button>;
13}

Variantes

Predeterminado (Default)

1'use client';
2
3import { Button } from '@/components/ui/button';
4import { Toast, useToast } from '@/components/ui/toast';
5
6function ToastDemo() {
7 const { toast } = useToast();
8
9 return (
10 <Button
11 variant="outline"
12 onClick={() =>
13 toast({
14 title: 'Invitation sent',
15 description: 'Lucia Mendez gets access to Acme Studio once she accepts.',
16 })
17 }
18 >
19 Invite teammate
20 </Button>
21 );
22}
23
24export function Default() {
25 return (
26 <Toast.Provider>
27 <ToastDemo />
28 </Toast.Provider>
29 );
30}

Todas las Variantes

Cinco variantes: default, success, error, info y warning.
1'use client';
2
3import { Button } from '@/components/ui/button';
4import { Toast, useToast } from '@/components/ui/toast';
5
6const variants = [
7 {
8 label: 'Default',
9 options: {
10 title: 'Invitation sent',
11 description: 'Lucia Mendez gets access to Acme Studio once she accepts.',
12 },
13 },
14 {
15 label: 'Success',
16 options: {
17 title: 'Deployed to production',
18 description: 'checkout-flow built in 42s and is serving traffic.',
19 variant: 'success' as const,
20 },
21 },
22 {
23 label: 'Error',
24 options: {
25 title: 'Payment declined',
26 description: 'Visa ending 4242 was rejected by the issuing bank.',
27 variant: 'error' as const,
28 },
29 },
30 {
31 label: 'Info',
32 options: {
33 title: 'Export is being prepared',
34 description: 'We will email a download link to lucia@acmestudio.dev when it is ready.',
35 variant: 'info' as const,
36 },
37 },
38 {
39 label: 'Warning',
40 options: {
41 title: 'Approaching the rate limit',
42 description: 'You have used 9,400 of 10,000 requests this hour.',
43 variant: 'warning' as const,
44 },
45 },
46];
47
48function VariantsDemo() {
49 const { toast } = useToast();
50
51 return (
52 <div className="flex flex-wrap gap-2">
53 {variants.map((variant) => (
54 <Button key={variant.label} variant="outline" onClick={() => toast(variant.options)}>
55 {variant.label}
56 </Button>
57 ))}
58 </div>
59 );
60}
61
62export function Variants() {
63 return (
64 <Toast.Provider>
65 <VariantsDemo />
66 </Toast.Provider>
67 );
68}

Con Acción

Toast con un botón de acción.

checkout-flow

Last deploy Mar 14, 3 environments

Active
1'use client';
2
3import * as React from 'react';
4import { Badge } from '@/components/ui/badge';
5import { Button } from '@/components/ui/button';
6import { Toast, useToast } from '@/components/ui/toast';
7import { Flex } from '@/components/ui/flex';
8
9function WithActionDemo() {
10 const { toast } = useToast();
11 const [archived, setArchived] = React.useState(false);
12
13 const archive = () => {
14 setArchived(true);
15 toast({
16 title: 'Project archived',
17 description: 'checkout-flow stopped serving traffic and moved to the archive.',
18 action: {
19 label: 'Undo',
20 onClick: () => setArchived(false),
21 },
22 });
23 };
24
25 return (
26 <Flex
27 align="center"
28 justify="between"
29 gap="4"
30 className="border-border bg-card w-full max-w-md rounded-xl border p-4"
31 >
32 <div className="min-w-0">
33 <p className="text-sm font-medium">checkout-flow</p>
34 <p className="text-muted-foreground text-xs">Last deploy Mar 14, 3 environments</p>
35 </div>
36 <Flex align="center" gap="2">
37 <Badge variant={archived ? 'secondary' : 'success'}>
38 {archived ? 'Archived' : 'Active'}
39 </Badge>
40 <Button variant="outline" size="sm" disabled={archived} onClick={archive}>
41 Archive
42 </Button>
43 </Flex>
44 </Flex>
45 );
46}
47
48export function WithAction() {
49 return (
50 <Toast.Provider>
51 <WithActionDemo />
52 </Toast.Provider>
53 );
54}

Posiciones

Elegí dónde aparecen los toasts en pantalla. Hacé click en una posición para seleccionarla y después disparar un toast.
1'use client';
2
3import * as React from 'react';
4import { Button } from '@/components/ui/button';
5import { Toast, useToast, type ToastPosition } from '@/components/ui/toast';
6
7const positions: { label: string; value: ToastPosition }[] = [
8 { label: 'Top Left', value: 'top-left' },
9 { label: 'Top Right', value: 'top-right' },
10 { label: 'Bottom Left', value: 'bottom-left' },
11 { label: 'Bottom Right', value: 'bottom-right' },
12];
13
14function PositionsInner() {
15 const { toast } = useToast();
16
17 return (
18 <Button
19 variant="outline"
20 onClick={() =>
21 toast({
22 title: 'Backup finished',
23 description: 'Nightly snapshot of acme-prod stored in eu-central-1.',
24 variant: 'success',
25 })
26 }
27 >
28 Run backup now
29 </Button>
30 );
31}
32
33export function Positions() {
34 const [position, setPosition] = React.useState<ToastPosition>('bottom-right');
35
36 return (
37 <Toast.Provider position={position}>
38 <div className="space-y-4">
39 <div className="grid grid-cols-2 gap-2 sm:flex sm:flex-wrap">
40 {positions.map((pos) => (
41 <Button
42 key={pos.value}
43 variant={position === pos.value ? 'default' : 'outline'}
44 size="sm"
45 onClick={() => setPosition(pos.value)}
46 >
47 {pos.label}
48 </Button>
49 ))}
50 </div>
51 <PositionsInner />
52 </div>
53 </Toast.Provider>
54 );
55}

Referencia de API

Toast.Provider

PropTipoPor defectoDescripción
childrenReact.ReactNodeEl contenido de la app.
maxToastsnumber5Número máximo de toasts visibles.
position"top-left" | "top-right" | "bottom-left" | "bottom-right""bottom-right"Dónde aparecen los toasts en pantalla.

useToast()

Devuelve un objeto con:
MétodoTipoDescripción
toast(options: ToastOptions) => stringMuestra un toast, devuelve su ID.
dismiss(id: string) => voidCierra un toast por su ID.

ToastOptions

PropTipoPor defectoDescripción
titlestringTítulo del toast (requerido).
descriptionstringDescripción opcional.
variant"default" | "success" | "error" | "info" | "warning""default"Variante visual.
durationnumber5000Delay de auto-cierre en ms. Usá 0 para desactivar.
action{ label: string; onClick: () => void }Botón de acción opcional.
¿Encontraste algo que mejorar?

¿Notaste un error, tipografía o detalle faltante en esta página? Ayúdanos a mejorar la documentación abriendo un issue en GitHub.

Crear un Issue
Ctrl+I