Skip to main content
Toast notification system powered by Sonner. Display temporary notifications for user actions and system events.

Import

import { Toaster, toast } from '@kivora/react';

Setup

Add Toaster to your root layout once:
import { Toaster } from '@kivora/react';

function App() {
  return (
    <>
      {/* Your app content */}
      <Toaster position="bottom-right" richColors />
    </>
  );
}

Usage

Use the toast function anywhere in your app:
import { toast, Button } from '@kivora/react';

function Example() {
  return (
    <Button
      label="Show Toast"
      onClick={() => toast('Hello world!')}
    />
  );
}

Variants

import { toast, Button } from '@kivora/react';

function ToastExamples() {
  return (
    <div className="flex gap-2">
      <Button
        label="Default"
        onClick={() => toast('This is a default toast')}
      />
      <Button
        label="Success"
        onClick={() => toast.success('Changes saved successfully!')}
      />
      <Button
        label="Error"
        onClick={() => toast.error('Something went wrong')}
      />
      <Button
        label="Warning"
        onClick={() => toast.warning('Unsaved changes')}
      />
      <Button
        label="Info"
        onClick={() => toast.info('New update available')}
      />
    </div>
  );
}

With Description

toast('Event created', {
  description: 'Your event has been scheduled for tomorrow at 10 AM',
});

toast.success('Deployment complete', {
  description: 'Your application is now live at app.example.com',
});

With Actions

toast('Meeting invitation', {
  description: 'Team sync at 3 PM today',
  action: {
    label: 'Accept',
    onClick: () => console.log('Accepted'),
  },
});

toast.error('Failed to save', {
  description: 'Could not save your changes',
  action: {
    label: 'Retry',
    onClick: () => saveChanges(),
  },
});

Custom Duration

// Show for 5 seconds
toast('Quick message', { duration: 5000 });

// Show until dismissed
toast('Important notice', { duration: Infinity });

Promise Toasts

Show loading, success, and error states automatically:
import { toast, Button } from '@kivora/react';

function SaveButton() {
  const handleSave = async () => {
    const promise = fetch('/api/save', { method: 'POST' });

    toast.promise(promise, {
      loading: 'Saving...',
      success: 'Saved successfully!',
      error: 'Failed to save',
    });
  };

  return <Button label="Save" onClick={handleSave} />;
}
With data:
const promise = fetchUser(id);

toast.promise(promise, {
  loading: 'Loading user...',
  success: (data) => `Welcome back, ${data.name}!`,
  error: (err) => `Error: ${err.message}`,
});

Dismissing Toasts

// Dismiss specific toast
const toastId = toast('Processing...');
toast.dismiss(toastId);

// Dismiss all toasts
toast.dismiss();

Custom Toast ID

// Prevent duplicate toasts
toast('Notification', { id: 'unique-id' });

Loading Toast

function UploadFile() {
  const handleUpload = async () => {
    const toastId = toast.loading('Uploading file...');

    try {
      await uploadFile();
      toast.success('File uploaded!', { id: toastId });
    } catch (error) {
      toast.error('Upload failed', { id: toastId });
    }
  };

  return <Button label="Upload" onClick={handleUpload} />;
}

Custom Components

toast.custom((t) => (
  <div className="bg-card border border-border rounded-lg p-4 shadow-lg">
    <div className="flex items-center gap-3">
      <div className="w-10 h-10 rounded-full bg-blue-500" />
      <div>
        <p className="font-semibold">John Doe</p>
        <p className="text-sm text-muted-foreground">Sent you a message</p>
      </div>
    </div>
  </div>
));

Positions

Configure position in the Toaster component:
<Toaster position="top-left" />
<Toaster position="top-center" />
<Toaster position="top-right" />
<Toaster position="bottom-left" />
<Toaster position="bottom-center" />
<Toaster position="bottom-right" />

Rich Colors

Enable colored backgrounds for variants:
<Toaster richColors />

Expand by Default

Show multiple toasts expanded:
<Toaster expand />

Close Button

Add close button to all toasts:
<Toaster closeButton />

Complete Example

import { Toaster, toast, Button } from '@kivora/react';

function App() {
  return (
    <div>
      <div className="flex gap-2 p-4">
        <Button
          label="Save"
          onClick={() => {
            toast.promise(
              fetch('/api/save', { method: 'POST' }),
              {
                loading: 'Saving...',
                success: 'Saved!',
                error: 'Failed',
              }
            );
          }}
        />
        <Button
          label="Delete"
          variant="destructive"
          onClick={() => {
            toast.error('Delete failed', {
              description: 'You do not have permission',
              action: {
                label: 'Contact admin',
                onClick: () => console.log('Contact'),
              },
            });
          }}
        />
      </div>
      <Toaster position="bottom-right" richColors closeButton />
    </div>
  );
}

Toaster Props

position
string
default:"bottom-right"
Position of the toast container. Options: top-left, top-center, top-right, bottom-left, bottom-center, bottom-right
richColors
boolean
default:"false"
Enable colored backgrounds for success, error, warning, and info toasts
expand
boolean
default:"false"
Show all toasts expanded by default
closeButton
boolean
default:"false"
Show close button on all toasts
duration
number
default:"4000"
Default duration in milliseconds for all toasts
visibleToasts
number
default:"3"
Maximum number of toasts visible at once

Toast Options

description
string
Additional description text below the main message
duration
number
default:"4000"
How long the toast is shown in milliseconds. Use Infinity to keep it until dismissed
action
{ label: string; onClick: () => void }
Action button with label and click handler
id
string
Custom ID for the toast. Useful for preventing duplicates or updating existing toasts
onDismiss
() => void
Callback fired when toast is dismissed
onAutoClose
() => void
Callback fired when toast auto-closes after duration

API Methods

// Basic variants
toast(message: string, options?: ToastOptions)
toast.success(message: string, options?: ToastOptions)
toast.error(message: string, options?: ToastOptions)
toast.warning(message: string, options?: ToastOptions)
toast.info(message: string, options?: ToastOptions)
toast.loading(message: string, options?: ToastOptions)

// Promise handling
toast.promise(promise: Promise, {
  loading: string,
  success: string | ((data) => string),
  error: string | ((error) => string),
})

// Custom content
toast.custom((toastId) => ReactNode)

// Dismiss
toast.dismiss(toastId?: string)

Best Practices

  • Use success toasts for completed actions
  • Use error toasts with actionable recovery options
  • Keep messages concise and clear
  • Use descriptions for additional context
  • Provide actions for important notifications
  • Don’t overuse toasts - they should be meaningful
  • Position toasts where they won’t block important content

Accessibility

  • Automatically announced by screen readers
  • Keyboard accessible actions
  • Respects prefers-reduced-motion
  • Proper ARIA labels
  • Focus management for actions

Build docs developers (and LLMs) love