Skip to Content
Hashti Design System
Components

Toast

Temporary floating notification popping up at the edge of the screen to acknowledge asynchronous actions.

Toast

Toasts are transient, floating notifications that appear in the viewport corner to acknowledge asynchronous events—such as saving a draft, copying a link to the clipboard, or completing a background sync.

Built on React Aria Components’ toast architecture, Hashti’s toast system features automatic queueing, configurable timeouts, polite live region announcements, and full keyboard dismissal.

ToastTransient notification toast with automated dismissal.

Import

import { ToastProvider, useToast } from "@hashti/react";

Setup & Architecture

To use toasts anywhere in your application, place <ToastProvider> near the root of your component tree (for example, inside your root layout or application shell). All child components can then dispatch toasts using the useToast() hook.

// Root application layout or provider wrapper
import { Theme, ToastProvider } from "@hashti/react";

export function AppShell({ children }: { children: React.ReactNode }) {
  return (
    <Theme theme="frame-light">
      <ToastProvider>{children}</ToastProvider>
    </Theme>
  );
}

Examples

Dispatching Toasts with useToast()

Call toast.add() inside event handlers or promise resolutions to surface instant feedback:

import { useToast, Button } from "@hashti/react";

export function BasicToastExample() {
  const toast = useToast();

  const handleSave = () => {
    toast.add({
      title: "Project saved",
      description: "All architectural changes were persisted successfully.",
      kind: "success",
    });
  };

  return (
    <Button variant="primary" onPress={handleSave}>
      Save Project
    </Button>
  );
}

Toast Kinds (Severities)

Toasts support Hashti’s four standard feedback kinds: info, success, warning, and error.

import { useToast, Button } from "@hashti/react";

export function ToastKindsExample() {
  const toast = useToast();

  return (
    <div className="flex flex-wrap gap-3">
      <Button
        variant="secondary"
        onPress={() =>
          toast.add({
            title: "Information",
            description: "New software update is available in the background.",
            kind: "info",
          })
        }
      >
        Info Toast
      </Button>

      <Button
        variant="secondary"
        onPress={() =>
          toast.add({
            title: "Changes Published",
            description: "Your design system tokens have been synced.",
            kind: "success",
          })
        }
      >
        Success Toast
      </Button>

      <Button
        variant="secondary"
        onPress={() =>
          toast.add({
            title: "Rate Limit Approaching",
            description: "85% of your hourly API quota has been consumed.",
            kind: "warning",
          })
        }
      >
        Warning Toast
      </Button>

      <Button
        variant="danger"
        onPress={() =>
          toast.add({
            title: "Upload Failed",
            description: "Could not establish connection to the remote cluster.",
            kind: "error",
          })
        }
      >
        Error Toast
      </Button>
    </div>
  );
}

Auto-Dismiss Duration & Custom Timeouts

By default, toasts automatically dismiss after 5,000 milliseconds (5 seconds). You can customize the duration per toast via options.timeout:

import { useToast, Button } from "@hashti/react";

export function CustomTimeoutExample() {
  const toast = useToast();

  const handleQuickToast = () => {
    toast.add(
      {
        title: "Copied to clipboard!",
        kind: "info",
      },
      { timeout: 2000 }, // Dismisses after 2 seconds
    );
  };

  const handlePersistentToast = () => {
    toast.add(
      {
        title: "Large migration running...",
        description: "This background job will take several minutes to complete.",
        kind: "warning",
      },
      { timeout: 15000 }, // Extended to 15 seconds
    );
  };

  return (
    <div className="flex gap-4">
      <Button variant="ghost" onPress={handleQuickToast}>
        Brief Toast (2s)
      </Button>
      <Button variant="ghost" onPress={handlePersistentToast}>
        Long Toast (15s)
      </Button>
    </div>
  );
}

Programmatic Toast Dismissal

The toast.add() method returns a unique string identifier that can be passed to toast.close(id) to manually dismiss a toast:

import { useRef } from "react";
import { useToast, Button } from "@hashti/react";

export function ProgrammaticDismissExample() {
  const toast = useToast();
  const activeToastKey = useRef<string | null>(null);

  const startTask = () => {
    activeToastKey.current = toast.add(
      {
        title: "Syncing data...",
        description: "Contacting primary replica node.",
        kind: "info",
      },
      { timeout: 30000 },
    );
  };

  const completeTask = () => {
    if (activeToastKey.current) {
      toast.close(activeToastKey.current);
      activeToastKey.current = null;
    }
    toast.add({
      title: "Data synchronized successfully!",
      kind: "success",
    });
  };

  return (
    <div className="flex gap-3">
      <Button variant="secondary" onPress={startTask}>
        Start Background Sync
      </Button>
      <Button variant="primary" onPress={completeTask}>
        Finish & Close
      </Button>
    </div>
  );
}

API Reference

useToast() Hook

The useToast() hook returns an object with the following methods:

MethodParametersReturnsDescription
add(message: ToastMessage, options?: ToastOptions)stringAdds a new toast to the queue and returns its unique ID key.
close(key: string)voidCloses and removes the toast with the specified ID key.

ToastMessage Object

PropertyTypeDefaultDescription
titlestringRequiredThe bold heading text displayed in the toast notification.
descriptionstring—Additional supporting description text.
kind'info' | 'success' | 'warning' | 'error''info'Semantic kind determining the toast icon and border accent.
variant'subtle' | 'solid' | 'bordered''subtle'Visual style variant for high or low contrast rendering.

ToastOptions Object

PropertyTypeDefaultDescription
timeoutnumber5000Duration in milliseconds before the toast automatically fades away.
prioritynumber0Queue priority determining order when multiple toasts arrive simultaneously.

Accessibility (a11y)

  • Polite Live Announcements: Toasts render within a <ToastRegion> mapped to aria-live="polite". Assistive technologies queue the notification and read it aloud as soon as the user is idle, avoiding jarring interruptions during typing or reading.
  • Keyboard Dismissal: Every toast includes a focusable close button equipped with aria-label="Dismiss notification". Users navigating via keyboard can tab to the button and press Enter or Space to dismiss.
  • Timing Guidelines (WCAG 2.2.1): Critical error messages or required actions should not rely solely on auto-dismissing toasts. Because users with reading difficulties or screen magnifiers may need more time to comprehend content, provide ample duration or consider using Alert or InlineNotification for essential recovery instructions.
  • Maximum Visible Count: The toast queue limits visible toasts to 3 at a time to prevent overcrowding the screen and overwhelming the user’s field of view.

WAI-ARIA & Data Attributes

AttributeTargetDescription
[data-entering]ToastApplied during toast slide-in transition.
[data-exiting]ToastApplied during toast dismissal transition.