Meet Frontfriend.Your brand. Your rules. Your agents, connected.Explore what’s new

Toast

A succinct message that is displayed temporarily.

Interactive preview

Rendered from the shared Frontfriend stories with React Base, the same preview Studio shows. Styling comes from your Design System; the code below is native to Base UI.

Installation

Complete project setup first. Your configuration must select react/base and include your Design System ID.

pnpm exec frontfriend download toast -f react --primitive base

Review dependencies reported by the downloader and keep your source changes in version control.

Usage

import {
  createToastManager,
  ToastProvider,
  useToastManager,
  ToastPortal,
  ToastViewport,
  Toast,
  ToastContent,
  ToastTitle,
  ToastDescription,
  ToastAction,
  ToastClose,
} from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
import { cn } from "@frontfriend/sdk/lib/react/utils";
import { ffdc, config } from "@frontfriend/sdk";
import { Toast as ToastPrimitive } from "@base-ui/react/toast";
import * as React from "react";
type DemoProps = {
  title?: string;
  description?: string;
  action?: boolean;
  cancel?: boolean;
  variant?: "neutral" | "destructive" | "info" | "warning" | "success";
};
const styling = ffdc(config || {}).toast;
function Notifications({
  title,
  description,
  action,
  cancel,
  variant = "neutral",
}: DemoProps) {
  const { toasts, add } = useToastManager<{
    cancel?: boolean;
  }>();
  return (
    <>
      <Button
        variant="tertiary"
        onClick={() =>
          add({
            title,
            description,
            type: variant === "destructive" ? "error" : variant,
            actionProps: action ? { children: "Action" } : undefined,
            data: { cancel },
          })
        }
      >
        Show Toast
      </Button>
      <ToastPortal>
        <ToastViewport>
          {toasts.map((item) => (
            <Toast key={item.id} toast={item} variant={variant}>
              <ToastContent>
                <div className={cn(styling.slots.content)}>
                  <ToastTitle />
                  <ToastDescription />
                </div>
                <ToastAction />
                {item.data?.cancel && (
                  <ToastPrimitive.Close
                    data-slot="toast-cancel"
                    render={<Button variant="tertiary" size="sm" />}
                  >
                    Undo
                  </ToastPrimitive.Close>
                )}
                <ToastClose />
              </ToastContent>
            </Toast>
          ))}
        </ToastViewport>
      </ToastPortal>
    </>
  );
}
export default function ToastExample() {
  const [manager] = React.useState(() =>
    createToastManager<{
      cancel?: boolean;
    }>(),
  );
  return (
    <ToastProvider toastManager={manager}>
      <Notifications variant="neutral" title="Saved" description="Your changes were saved." action={false} cancel={false} />
    </ToastProvider>
  );
}

Examples

Default

import {
  createToastManager,
  ToastProvider,
  useToastManager,
  ToastPortal,
  ToastViewport,
  Toast,
  ToastContent,
  ToastTitle,
  ToastDescription,
  ToastAction,
  ToastClose,
} from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
import { cn } from "@frontfriend/sdk/lib/react/utils";
import { ffdc, config } from "@frontfriend/sdk";
import { Toast as ToastPrimitive } from "@base-ui/react/toast";
import * as React from "react";
type DemoProps = {
  title?: string;
  description?: string;
  action?: boolean;
  cancel?: boolean;
  variant?: "neutral" | "destructive" | "info" | "warning" | "success";
};
const styling = ffdc(config || {}).toast;
function Notifications({
  title,
  description,
  action,
  cancel,
  variant = "neutral",
}: DemoProps) {
  const { toasts, add } = useToastManager<{
    cancel?: boolean;
  }>();
  return (
    <>
      <Button
        variant="tertiary"
        onClick={() =>
          add({
            title,
            description,
            type: variant === "destructive" ? "error" : variant,
            actionProps: action ? { children: "Action" } : undefined,
            data: { cancel },
          })
        }
      >
        Show Toast
      </Button>
      <ToastPortal>
        <ToastViewport>
          {toasts.map((item) => (
            <Toast key={item.id} toast={item} variant={variant}>
              <ToastContent>
                <div className={cn(styling.slots.content)}>
                  <ToastTitle />
                  <ToastDescription />
                </div>
                <ToastAction />
                {item.data?.cancel && (
                  <ToastPrimitive.Close
                    data-slot="toast-cancel"
                    render={<Button variant="tertiary" size="sm" />}
                  >
                    Undo
                  </ToastPrimitive.Close>
                )}
                <ToastClose />
              </ToastContent>
            </Toast>
          ))}
        </ToastViewport>
      </ToastPortal>
    </>
  );
}
export default function ToastExample() {
  const [manager] = React.useState(() =>
    createToastManager<{
      cancel?: boolean;
    }>(),
  );
  return (
    <ToastProvider toastManager={manager}>
      <Notifications variant="neutral" title="Title" description="Description" action cancel />
    </ToastProvider>
  );
}

With Title Description

import {
  createToastManager,
  ToastProvider,
  useToastManager,
  ToastPortal,
  ToastViewport,
  Toast,
  ToastContent,
  ToastTitle,
  ToastDescription,
  ToastAction,
  ToastClose,
} from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
import { cn } from "@frontfriend/sdk/lib/react/utils";
import { ffdc, config } from "@frontfriend/sdk";
import { Toast as ToastPrimitive } from "@base-ui/react/toast";
import * as React from "react";
type DemoProps = {
  title?: string;
  description?: string;
  action?: boolean;
  cancel?: boolean;
  variant?: "neutral" | "destructive" | "info" | "warning" | "success";
};
const styling = ffdc(config || {}).toast;
function Notifications({
  title,
  description,
  action,
  cancel,
  variant = "neutral",
}: DemoProps) {
  const { toasts, add } = useToastManager<{
    cancel?: boolean;
  }>();
  return (
    <>
      <Button
        variant="tertiary"
        onClick={() =>
          add({
            title,
            description,
            type: variant === "destructive" ? "error" : variant,
            actionProps: action ? { children: "Action" } : undefined,
            data: { cancel },
          })
        }
      >
        Show Toast
      </Button>
      <ToastPortal>
        <ToastViewport>
          {toasts.map((item) => (
            <Toast key={item.id} toast={item} variant={variant}>
              <ToastContent>
                <div className={cn(styling.slots.content)}>
                  <ToastTitle />
                  <ToastDescription />
                </div>
                <ToastAction />
                {item.data?.cancel && (
                  <ToastPrimitive.Close
                    data-slot="toast-cancel"
                    render={<Button variant="tertiary" size="sm" />}
                  >
                    Undo
                  </ToastPrimitive.Close>
                )}
                <ToastClose />
              </ToastContent>
            </Toast>
          ))}
        </ToastViewport>
      </ToastPortal>
    </>
  );
}
export default function ToastExample() {
  const [manager] = React.useState(() =>
    createToastManager<{
      cancel?: boolean;
    }>(),
  );
  return (
    <ToastProvider toastManager={manager}>
      <Notifications variant="neutral" title="Event created" description="Friday, February 10, 2023 at 5:57 PM" action={false} cancel={false} />
    </ToastProvider>
  );
}

With Action

import {
  createToastManager,
  ToastProvider,
  useToastManager,
  ToastPortal,
  ToastViewport,
  Toast,
  ToastContent,
  ToastTitle,
  ToastDescription,
  ToastAction,
  ToastClose,
} from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
import { cn } from "@frontfriend/sdk/lib/react/utils";
import { ffdc, config } from "@frontfriend/sdk";
import { Toast as ToastPrimitive } from "@base-ui/react/toast";
import * as React from "react";
type DemoProps = {
  title?: string;
  description?: string;
  action?: boolean;
  cancel?: boolean;
  variant?: "neutral" | "destructive" | "info" | "warning" | "success";
};
const styling = ffdc(config || {}).toast;
function Notifications({
  title,
  description,
  action,
  cancel,
  variant = "neutral",
}: DemoProps) {
  const { toasts, add } = useToastManager<{
    cancel?: boolean;
  }>();
  return (
    <>
      <Button
        variant="tertiary"
        onClick={() =>
          add({
            title,
            description,
            type: variant === "destructive" ? "error" : variant,
            actionProps: action ? { children: "Action" } : undefined,
            data: { cancel },
          })
        }
      >
        Show Toast
      </Button>
      <ToastPortal>
        <ToastViewport>
          {toasts.map((item) => (
            <Toast key={item.id} toast={item} variant={variant}>
              <ToastContent>
                <div className={cn(styling.slots.content)}>
                  <ToastTitle />
                  <ToastDescription />
                </div>
                <ToastAction />
                {item.data?.cancel && (
                  <ToastPrimitive.Close
                    data-slot="toast-cancel"
                    render={<Button variant="tertiary" size="sm" />}
                  >
                    Undo
                  </ToastPrimitive.Close>
                )}
                <ToastClose />
              </ToastContent>
            </Toast>
          ))}
        </ToastViewport>
      </ToastPortal>
    </>
  );
}
export default function ToastExample() {
  const [manager] = React.useState(() =>
    createToastManager<{
      cancel?: boolean;
    }>(),
  );
  return (
    <ToastProvider toastManager={manager}>
      <Notifications variant="neutral" title="Title" description="Description" action cancel />
    </ToastProvider>
  );
}

Destructive

import {
  createToastManager,
  ToastProvider,
  useToastManager,
  ToastPortal,
  ToastViewport,
  Toast,
  ToastContent,
  ToastTitle,
  ToastDescription,
  ToastAction,
  ToastClose,
} from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
import { cn } from "@frontfriend/sdk/lib/react/utils";
import { ffdc, config } from "@frontfriend/sdk";
import { Toast as ToastPrimitive } from "@base-ui/react/toast";
import * as React from "react";
type DemoProps = {
  title?: string;
  description?: string;
  action?: boolean;
  cancel?: boolean;
  variant?: "neutral" | "destructive" | "info" | "warning" | "success";
};
const styling = ffdc(config || {}).toast;
function Notifications({
  title,
  description,
  action,
  cancel,
  variant = "neutral",
}: DemoProps) {
  const { toasts, add } = useToastManager<{
    cancel?: boolean;
  }>();
  return (
    <>
      <Button
        variant="tertiary"
        onClick={() =>
          add({
            title,
            description,
            type: variant === "destructive" ? "error" : variant,
            actionProps: action ? { children: "Action" } : undefined,
            data: { cancel },
          })
        }
      >
        Show Toast
      </Button>
      <ToastPortal>
        <ToastViewport>
          {toasts.map((item) => (
            <Toast key={item.id} toast={item} variant={variant}>
              <ToastContent>
                <div className={cn(styling.slots.content)}>
                  <ToastTitle />
                  <ToastDescription />
                </div>
                <ToastAction />
                {item.data?.cancel && (
                  <ToastPrimitive.Close
                    data-slot="toast-cancel"
                    render={<Button variant="tertiary" size="sm" />}
                  >
                    Undo
                  </ToastPrimitive.Close>
                )}
                <ToastClose />
              </ToastContent>
            </Toast>
          ))}
        </ToastViewport>
      </ToastPortal>
    </>
  );
}
export default function ToastExample() {
  const [manager] = React.useState(() =>
    createToastManager<{
      cancel?: boolean;
    }>(),
  );
  return (
    <ToastProvider toastManager={manager}>
      <Notifications variant="destructive" title="Something went wrong" description="Please try again." action cancel={false} />
    </ToastProvider>
  );
}

Success

import {
  createToastManager,
  ToastProvider,
  useToastManager,
  ToastPortal,
  ToastViewport,
  Toast,
  ToastContent,
  ToastTitle,
  ToastDescription,
  ToastAction,
  ToastClose,
} from "@/components/ui/toast";
import { Button } from "@/components/ui/button";
import { cn } from "@frontfriend/sdk/lib/react/utils";
import { ffdc, config } from "@frontfriend/sdk";
import { Toast as ToastPrimitive } from "@base-ui/react/toast";
import * as React from "react";
type DemoProps = {
  title?: string;
  description?: string;
  action?: boolean;
  cancel?: boolean;
  variant?: "neutral" | "destructive" | "info" | "warning" | "success";
};
const styling = ffdc(config || {}).toast;
function Notifications({
  title,
  description,
  action,
  cancel,
  variant = "neutral",
}: DemoProps) {
  const { toasts, add } = useToastManager<{
    cancel?: boolean;
  }>();
  return (
    <>
      <Button
        variant="tertiary"
        onClick={() =>
          add({
            title,
            description,
            type: variant === "destructive" ? "error" : variant,
            actionProps: action ? { children: "Action" } : undefined,
            data: { cancel },
          })
        }
      >
        Show Toast
      </Button>
      <ToastPortal>
        <ToastViewport>
          {toasts.map((item) => (
            <Toast key={item.id} toast={item} variant={variant}>
              <ToastContent>
                <div className={cn(styling.slots.content)}>
                  <ToastTitle />
                  <ToastDescription />
                </div>
                <ToastAction />
                {item.data?.cancel && (
                  <ToastPrimitive.Close
                    data-slot="toast-cancel"
                    render={<Button variant="tertiary" size="sm" />}
                  >
                    Undo
                  </ToastPrimitive.Close>
                )}
                <ToastClose />
              </ToastContent>
            </Toast>
          ))}
        </ToastViewport>
      </ToastPortal>
    </>
  );
}
export default function ToastExample() {
  const [manager] = React.useState(() =>
    createToastManager<{
      cancel?: boolean;
    }>(),
  );
  return (
    <ToastProvider toastManager={manager}>
      <Notifications variant="success" title="Saved" description="Your changes were saved." action={false} cancel={false} />
    </ToastProvider>
  );
}

API reference

Frontfriend-owned props. Native HTML and inherited primitive props remain documented by Base UI.

Prop Type Default Description
variant "neutral" | "destructive" | "warning" | "success" | "info" | null —

Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.