Lightweight React notification library with customizable toast notifications and headless hooks support.
npx @tessl/cli install tessl/npm-react-hot-toast@2.6.0React Hot Toast is a lightweight React notification library that provides beautiful, customizable toast notifications with excellent performance and developer experience. It offers both a complete UI solution and headless hooks for custom implementations, handling animations, positioning, and state management automatically.
npm install react-hot-toastimport toast, { Toaster } from "react-hot-toast";For headless usage:
import toast, { useToaster, useToasterStore } from "react-hot-toast/headless";CommonJS:
const toast = require("react-hot-toast");
const { Toaster } = require("react-hot-toast");import toast, { Toaster } from "react-hot-toast";
function App() {
const notify = () => toast('Here is your toast.');
return (
<div>
<button onClick={notify}>Make me a toast</button>
<Toaster />
</div>
);
}React Hot Toast is built around several key components:
toast()) with method variants for different typesToaster container, ToastBar display, and icon componentsuseToaster and useToasterStore for custom implementationsCore toast creation functions for displaying notifications with different types and styling.
/**
* Creates a basic toast notification
* @param message - Content to display (string, JSX, or function)
* @param options - Toast configuration options
* @returns Toast ID string for dismissal/updates
*/
function toast(message: Renderable, options?: ToastOptions): string;
/**
* Creates a success toast with checkmark icon
* @param message - Content to display
* @param options - Toast configuration options
* @returns Toast ID string
*/
toast.success(message: Renderable, options?: ToastOptions): string;
/**
* Creates an error toast with error icon
* @param message - Content to display
* @param options - Toast configuration options
* @returns Toast ID string
*/
toast.error(message: Renderable, options?: ToastOptions): string;
/**
* Creates a loading toast with spinning loader
* @param message - Content to display
* @param options - Toast configuration options
* @returns Toast ID string
*/
toast.loading(message: Renderable, options?: ToastOptions): string;
/**
* Creates a custom toast with user-provided content
* @param message - Custom content (typically JSX)
* @param options - Toast configuration options
* @returns Toast ID string
*/
toast.custom(message: Renderable, options?: ToastOptions): string;Automatic toast updates based on promise resolution, perfect for API calls and async operations.
/**
* Creates a loading toast that automatically updates based on promise resolution
* @param promise - Promise to track or function returning promise
* @param messages - Messages for different states
* @param options - Toast configuration with per-state overrides
* @returns The original promise for chaining
*/
toast.promise<T>(
promise: Promise<T> | (() => Promise<T>),
messages: {
loading: Renderable;
success?: ValueOrFunction<Renderable, T>;
error?: ValueOrFunction<Renderable, any>;
},
options?: DefaultToastOptions
): Promise<T>;Usage Examples:
// Basic promise toast
const myPromise = fetch('/api/data');
toast.promise(myPromise, {
loading: 'Loading...',
success: 'Data loaded successfully!',
error: 'Failed to load data'
});
// Dynamic messages based on result
toast.promise(
saveUser(userData),
{
loading: 'Saving user...',
success: (user) => `Successfully saved ${user.name}!`,
error: (err) => `Error: ${err.message}`
}
);Functions for dismissing and removing toasts from the display.
/**
* Dismisses a toast or all toasts with animation
* @param toastId - ID of toast to dismiss (optional, dismisses all if not provided)
* @param toasterId - Target specific toaster instance (optional)
*/
toast.dismiss(toastId?: string, toasterId?: string): void;
/**
* Dismisses all toasts in specified or all toasters
* @param toasterId - Target specific toaster instance (optional)
*/
toast.dismissAll(toasterId?: string): void;
/**
* Immediately removes a toast without animation
* @param toastId - ID of toast to remove (optional, removes all if not provided)
* @param toasterId - Target specific toaster instance (optional)
*/
toast.remove(toastId?: string, toasterId?: string): void;
/**
* Immediately removes all toasts without animation
* @param toasterId - Target specific toaster instance (optional)
*/
toast.removeAll(toasterId?: string): void;React components for rendering toasts with built-in styling and animations.
/**
* Main container component that renders all toasts
* @param props - Toaster configuration
*/
function Toaster(props: ToasterProps): JSX.Element;
interface ToasterProps {
/** Position for all toasts (default: 'top-center') */
position?: ToastPosition;
/** Default options applied to all toasts */
toastOptions?: DefaultToastOptions;
/** Render toasts in reverse order (newest at bottom) */
reverseOrder?: boolean;
/** Space between toasts in pixels (default: 8) */
gutter?: number;
/** Custom styles for the container */
containerStyle?: React.CSSProperties;
/** CSS class for the container */
containerClassName?: string;
/** Unique identifier for this toaster instance */
toasterId?: string;
/** Render function for custom toast components */
children?: (toast: Toast) => React.ReactElement;
}
/**
* Default toast bar component with styling and animations
* @param props - Toast bar configuration
*/
function ToastBar(props: ToastBarProps): JSX.Element;
interface ToastBarProps {
/** Toast object to render */
toast: Toast;
/** Position override for this toast */
position?: ToastPosition;
/** Custom styles for the toast bar */
style?: React.CSSProperties;
/** Render function for custom content */
children?: (components: {
icon: Renderable;
message: Renderable;
}) => Renderable;
}
/**
* Icon component with animations for different toast types
* @param props - Icon configuration
*/
function ToastIcon(props: { toast: Toast }): JSX.Element;Animated icon components for different toast states.
/**
* Animated checkmark icon for success toasts
*/
function CheckmarkIcon(props: CheckmarkTheme): JSX.Element;
interface CheckmarkTheme {
/** Primary color (default: '#61d345') */
primary?: string;
/** Secondary color (default: '#fff') */
secondary?: string;
}
/**
* Animated error icon for error toasts
*/
function ErrorIcon(props: ErrorTheme): JSX.Element;
interface ErrorTheme {
/** Primary color (default: '#ff4b4b') */
primary?: string;
/** Secondary color (default: '#fff') */
secondary?: string;
}
/**
* Animated loader icon for loading toasts
*/
function LoaderIcon(props: LoaderTheme): JSX.Element;
interface LoaderTheme {
/** Primary color (default: '#616161') */
primary?: string;
/** Secondary color (default: '#e0e0e0') */
secondary?: string;
}React hooks for custom toast implementations without built-in UI components.
/**
* Main hook for managing toast state and handlers
* @param toastOptions - Default options for all toasts
* @param toasterId - Unique identifier for this toaster instance (default: 'default')
* @returns Toast state and handler functions
*/
function useToaster(
toastOptions?: DefaultToastOptions,
toasterId?: string
): {
toasts: Toast[];
handlers: {
updateHeight: (toastId: string, height: number) => void;
startPause: () => void;
endPause: () => void;
calculateOffset: (
toast: Toast,
opts?: {
reverseOrder?: boolean;
gutter?: number;
defaultPosition?: ToastPosition;
}
) => number;
};
};
/**
* Hook for accessing raw toast store state
* @param toastOptions - Default options for merging with toast state
* @param toasterId - Unique identifier for this toaster instance
* @returns Current toaster state
*/
function useToasterStore(
toastOptions?: DefaultToastOptions,
toasterId?: string
): ToasterState;
interface ToasterState {
/** Array of current toasts */
toasts: Toast[];
/** Toaster configuration settings */
settings: ToasterSettings;
/** Timestamp when toasts were paused (undefined if not paused) */
pausedAt: number | undefined;
}
/** Toaster configuration settings */
interface ToasterSettings {
/** Maximum number of toasts to show simultaneously */
toastLimit: number;
}Helper functions for working with dynamic values and toast state.
/**
* Resolves a value or function to its final value
* @param valOrFunction - Static value or function that returns value
* @param arg - Argument passed to function if valOrFunction is a function
* @returns Resolved value
*/
function resolveValue<TValue, TArg>(
valOrFunction: ValueOrFunction<TValue, TArg>,
arg: TArg
): TValue;/** Content that can be rendered in a toast */
type Renderable = React.ReactElement | string | null;
/** Toast type determining icon and default styling */
type ToastType = 'success' | 'error' | 'loading' | 'blank' | 'custom';
/** Available positions for toast placement */
type ToastPosition =
| 'top-left'
| 'top-center'
| 'top-right'
| 'bottom-left'
| 'bottom-center'
| 'bottom-right';
/** Function that receives an argument and returns a value */
type ValueFunction<TValue, TArg> = (arg: TArg) => TValue;
/** Either a static value or a function that returns the value */
type ValueOrFunction<TValue, TArg> = TValue | ValueFunction<TValue, TArg>;
/** Message content type used internally */
type Message = ValueOrFunction<Renderable, Toast>;
/** Complete toast object with all properties */
interface Toast {
/** Toast type determining appearance */
type: ToastType;
/** Unique identifier */
id: string;
/** Toaster instance this toast belongs to */
toasterId?: string;
/** Content to display (can be dynamic based on toast state) */
message: ValueOrFunction<Renderable, Toast>;
/** Custom icon override */
icon?: Renderable;
/** How long to show before auto-dismiss (ms, Infinity for manual) */
duration?: number;
/** Accumulated pause time (internal) */
pauseDuration: number;
/** Position override for this toast */
position?: ToastPosition;
/** Delay before removing from DOM after dismissal */
removeDelay?: number;
/** Accessibility attributes */
ariaProps: {
role: 'status' | 'alert';
'aria-live': 'assertive' | 'off' | 'polite';
};
/** Custom CSS styles */
style?: React.CSSProperties;
/** CSS class name */
className?: string;
/** Icon color theme */
iconTheme?: IconTheme;
/** Creation timestamp */
createdAt: number;
/** Whether toast is currently visible */
visible: boolean;
/** Whether toast has been dismissed */
dismissed: boolean;
/** Calculated height for positioning (internal) */
height?: number;
}
/** Configuration options for individual toasts */
type ToastOptions = Partial<Pick<
Toast,
| 'id'
| 'icon'
| 'duration'
| 'ariaProps'
| 'className'
| 'style'
| 'position'
| 'iconTheme'
| 'toasterId'
| 'removeDelay'
>>;
/** Default options with per-type overrides */
type DefaultToastOptions = ToastOptions & {
[key in ToastType]?: ToastOptions;
};
/** Icon color theme */
interface IconTheme {
/** Primary color */
primary: string;
/** Secondary color */
secondary: string;
}/** Internal wrapper props for toast positioning */
interface ToastWrapperProps {
/** Toast unique identifier */
id: string;
/** CSS class name */
className?: string;
/** Custom styles */
style?: React.CSSProperties;
/** Callback when toast height changes */
onHeightUpdate: (id: string, height: number) => void;
/** Toast content */
children?: React.ReactNode;
}
/** Toaster configuration settings */
interface ToasterSettings {
/** Maximum number of toasts to show simultaneously */
toastLimit: number;
}React Hot Toast uses different default durations based on toast type:
import { Toaster } from "react-hot-toast";
function CustomToaster() {
return (
<Toaster>
{(t) => (
<div
className={`${
t.visible ? 'animate-enter' : 'animate-leave'
} custom-toast`}
>
<div>{t.message}</div>
<button onClick={() => toast.dismiss(t.id)}>×</button>
</div>
)}
</Toaster>
);
}// Different toasters for different areas
toast('Global notification');
toast('Header notification', { toasterId: 'header' });
// Render toasters
<Toaster /> {/* Default toaster */}
<Toaster toasterId="header" position="top-right" />import { useToaster } from "react-hot-toast/headless";
function CustomToastContainer() {
const { toasts, handlers } = useToaster();
return (
<div
onMouseEnter={handlers.startPause}
onMouseLeave={handlers.endPause}
>
{toasts.map((toast) => (
<div
key={toast.id}
style={{
transform: `translateY(${handlers.calculateOffset(toast)}px)`
}}
>
{typeof toast.message === 'function'
? toast.message(toast)
: toast.message}
</div>
))}
</div>
);
}