# Sonner

Sonner is an opinionated toast component for React that provides a comprehensive solution for displaying toast notifications. It offers a simple and intuitive API through a Toaster component and toast function, supporting various toast types including success, error, info, warning, loading, and custom toasts with actions.

## Package Information

- **Package Name**: sonner
- **Package Type**: npm
- **Language**: TypeScript
- **Installation**: `npm install sonner`

## Core Imports

```typescript
import { Toaster, toast } from "sonner";
```

For CommonJS:

```javascript
const { Toaster, toast } = require("sonner");
```

Additional imports for advanced usage:

```typescript
import { 
  Toaster, 
  toast, 
  useSonner,
  type ExternalToast,
  type ToasterProps,
  type ToastT
} from "sonner";
```

## Basic Usage

```typescript
import React from "react";
import { Toaster, toast } from "sonner";

function App() {
  return (
    <div>
      {/* Add Toaster component once in your app */}
      <Toaster />
      
      {/* Create toasts from anywhere */}
      <button onClick={() => toast("Hello World!")}>
        Show Toast
      </button>
      
      <button onClick={() => toast.success("Success!")}>
        Success Toast
      </button>
      
      <button onClick={() => toast.error("Something went wrong!")}>
        Error Toast
      </button>
    </div>
  );
}
```

## Architecture

Sonner is built around several key components:

- **Toaster Component**: The container that renders all toast messages with positioning and theming
- **Toast Function**: The primary API for creating different types of toast notifications
- **State Management**: Built-in observer pattern for managing toast lifecycle and updates
- **Toast Types**: Pre-configured toast variants (success, error, info, warning, loading) with appropriate styling
- **Promise Integration**: Automatic state management for async operations with loading, success, and error states
- **Customization System**: Comprehensive theming, positioning, and styling options
- **Interaction System**: Support for swipe gestures, hover pause, keyboard navigation, and accessibility

## Capabilities

### Core Toast Functions

Primary toast creation functions for displaying notifications with different visual styles and behaviors.

```typescript { .api }
function toast(message: string | React.ReactNode, options?: ExternalToast): string | number;

// Type-specific toast functions
namespace toast {
  function success(message: string | React.ReactNode, options?: ExternalToast): string | number;
  function error(message: string | React.ReactNode, options?: ExternalToast): string | number;
  function info(message: string | React.ReactNode, options?: ExternalToast): string | number;
  function warning(message: string | React.ReactNode, options?: ExternalToast): string | number;
  function loading(message: string | React.ReactNode, options?: ExternalToast): string | number;
  function message(message: string | React.ReactNode, options?: ExternalToast): string | number;
  function dismiss(id?: string | number): string | number | undefined;
  function promise<T>(promise: PromiseT<T>, options: PromiseData<T>): { unwrap(): Promise<T> } & (string | number);
  function custom(jsx: (id: string | number) => React.ReactElement, options?: ExternalToast): string | number;
  function getHistory(): ToastT[];
  function getToasts(): ToastT[];
}
```

[Core Toast Functions](./core-toast-functions.md)

### Toaster Component

The main React component that renders and manages all toast notifications with comprehensive configuration options.

```typescript { .api }
const Toaster: React.ForwardRefExoticComponent<ToasterProps & React.RefAttributes<HTMLElement>>;

interface ToasterProps {
  invert?: boolean;
  theme?: "light" | "dark" | "system";
  position?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top-center" | "bottom-center";
  hotkey?: string[];
  richColors?: boolean;
  expand?: boolean;
  duration?: number;
  gap?: number;
  visibleToasts?: number;
  closeButton?: boolean;
  toastOptions?: ToastOptions;
  className?: string;
  style?: React.CSSProperties;
  offset?: Offset;
  mobileOffset?: Offset;
  dir?: "rtl" | "ltr" | "auto";
  swipeDirections?: SwipeDirection[];
  /** @deprecated Use icons prop instead */
  loadingIcon?: React.ReactNode;
  icons?: ToastIcons;
  containerAriaLabel?: string;
  pauseWhenPageIsHidden?: boolean;
}
```

[Toaster Component](./toaster-component.md)

### Advanced Toast Features

Advanced toast functionality including promise integration, custom JSX content, and action buttons.

```typescript { .api }
// Promise-based toasts
function toast.promise<T>(
  promise: Promise<T> | (() => Promise<T>),
  options: PromiseData<T>
): { unwrap(): Promise<T> } & (string | number);

// Custom JSX toasts
function toast.custom(
  jsx: (id: string | number) => React.ReactElement,
  options?: ExternalToast
): string | number;

// Toast state management
function toast.getHistory(): ToastT[];
function toast.getToasts(): ToastT[];
```

[Advanced Toast Features](./advanced-toast-features.md)

### React Hooks

React hooks for integrating with toast state and managing toast notifications programmatically.

```typescript { .api }
function useSonner(): {
  toasts: ToastT[];
};
```

[React Hooks](./react-hooks.md)

## Core Types

```typescript { .api }
interface ExternalToast {
  id?: string | number;
  type?: "normal" | "action" | "success" | "info" | "warning" | "error" | "loading" | "default";
  icon?: React.ReactNode;
  jsx?: React.ReactNode;
  richColors?: boolean;
  invert?: boolean;
  closeButton?: boolean;
  dismissible?: boolean;
  description?: (() => React.ReactNode) | React.ReactNode;
  duration?: number;
  action?: Action | React.ReactNode;
  cancel?: Action | React.ReactNode;
  onDismiss?: (toast: ToastT) => void;
  onAutoClose?: (toast: ToastT) => void;
  cancelButtonStyle?: React.CSSProperties;
  actionButtonStyle?: React.CSSProperties;
  style?: React.CSSProperties;
  unstyled?: boolean;
  className?: string;
  classNames?: ToastClassnames;
  descriptionClassName?: string;
  position?: Position;
}

interface Action {
  label: React.ReactNode;
  onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
  actionButtonStyle?: React.CSSProperties;
}

interface ToastT {
  id: number | string;
  title?: (() => React.ReactNode) | React.ReactNode;
  type?: "normal" | "action" | "success" | "info" | "warning" | "error" | "loading" | "default";
  icon?: React.ReactNode;
  jsx?: React.ReactNode;
  richColors?: boolean;
  invert?: boolean;
  closeButton?: boolean;
  dismissible?: boolean;
  description?: (() => React.ReactNode) | React.ReactNode;
  duration?: number;
  delete?: boolean;
  action?: Action | React.ReactNode;
  cancel?: Action | React.ReactNode;
  onDismiss?: (toast: ToastT) => void;
  onAutoClose?: (toast: ToastT) => void;
  promise?: Promise<any> | (() => Promise<any>);
  cancelButtonStyle?: React.CSSProperties;
  actionButtonStyle?: React.CSSProperties;
  style?: React.CSSProperties;
  unstyled?: boolean;
  className?: string;
  classNames?: ToastClassnames;
  descriptionClassName?: string;
  position?: Position;
}

type Position = "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top-center" | "bottom-center";

type SwipeDirection = "top" | "right" | "bottom" | "left";

interface ToastClassnames {
  toast?: string;
  title?: string;
  description?: string;
  loader?: string;
  closeButton?: string;
  cancelButton?: string;
  actionButton?: string;
  success?: string;
  error?: string;
  info?: string;
  warning?: string;
  loading?: string;
  default?: string;
  content?: string;
  icon?: string;
}

interface ToastIcons {
  success?: React.ReactNode;
  info?: React.ReactNode;
  warning?: React.ReactNode;
  error?: React.ReactNode;
  loading?: React.ReactNode;
  close?: React.ReactNode;
}

type Offset = {
  top?: string | number;
  right?: string | number;
  bottom?: string | number;
  left?: string | number;
} | string | number;

interface PromiseData<ToastData = any> {
  loading?: string | React.ReactNode;
  success?: string | React.ReactNode | ((data: ToastData) => React.ReactNode | string | Promise<React.ReactNode | string>);
  error?: string | React.ReactNode | ((error: any) => React.ReactNode | string | Promise<React.ReactNode | string>);
  description?: string | React.ReactNode | ((data: any) => React.ReactNode | string | Promise<React.ReactNode | string>);
  finally?: () => void | Promise<void>;
}

type PromiseT<Data = any> = Promise<Data> | (() => Promise<Data>);

type PromiseExternalToast = Omit<ExternalToast, 'description'>;
```