Skip to content

Toast Notifications

Cartridge Controller provides a built-in toast notification system that allows you to display various types of notifications to users. The toast system is designed to work seamlessly across iframe boundaries, ensuring notifications are always visible even when called from within the keychain iframe.

Installation

Toast notifications are included with the main controller package:

npm install @cartridge/controller

Basic Usage

Import the toast function and call it with your notification options:

import { toast } from "@cartridge/controller";
 
// Show a simple error message
toast({
  variant: "error",
  message: "Transaction failed. Please try again.",
});

Toast Variants

The toast system supports six different variants, each designed for specific use cases:

Error Toast

Display error messages to users:

toast({
  variant: "error",
  message: "Failed to connect to wallet",
  duration: 5000, // Optional: 5 seconds
  position: "top-right", // Optional: positioning
});

Transaction Toast

Show transaction status updates:

toast({
  variant: "transaction",
  status: "confirming", // or "confirmed"
  label: "Transfer 100 ETH", // Optional: transaction description
  isExpanded: false, // Optional: expanded view
});

Network Switch Toast

Notify users about network changes:

toast({
  variant: "network-switch",
  networkName: "Starknet Mainnet",
  networkIcon: "https://example.com/starknet-icon.png", // Optional
});

Achievement Toast

Celebrate user achievements:

toast({
  variant: "achievement",
  title: "First Victory!",
  subtitle: "You won your first battle", // Optional
  xpAmount: 250,
  isDraft: false, // Optional: draft state
});

Quest Toast

Display quest-related notifications:

toast({
  variant: "quest",
  title: "Quest Completed",
  subtitle: "The Dragon's Lair has been conquered!",
});

Marketplace Toast

Show marketplace activity:

toast({
  variant: "marketplace",
  itemName: "Legendary Sword",
  itemImage: "https://example.com/sword.png",
  action: "purchased", // or "sold"
});

Configuration Options

Positioning

Toast notifications can be positioned at six different locations:

type ToastPosition = 
  | "top-left"
  | "top-right" 
  | "top-center"
  | "bottom-left"
  | "bottom-right"
  | "bottom-center";
 
toast({
  variant: "error",
  message: "Error message",
  position: "bottom-center",
});

Duration

Control how long toasts are displayed:

toast({
  variant: "error",
  message: "This will auto-dismiss after 3 seconds",
  duration: 3000, // milliseconds
});
 
// Persistent toast (user must manually close)
toast({
  variant: "error", 
  message: "This toast stays until manually closed",
  duration: 0, // or Infinity
});

Manual Dismissal

The toast() function returns a dismiss function:

const dismiss = toast({
  variant: "achievement",
  title: "Achievement Unlocked!",
  xpAmount: 100,
});
 
// Later, dismiss manually
setTimeout(() => {
  dismiss();
}, 2000);

Cross-Iframe Support

Toast notifications automatically work across iframe boundaries. When called from within an iframe (such as the Cartridge keychain), toasts will appear on the parent page to ensure maximum visibility.

// This works whether called from main page or iframe
toast({
  variant: "transaction",
  status: "confirmed",
  label: "Payment successful",
});

TypeScript Support

Full TypeScript definitions are provided for all toast options:

import { ToastOptions, ToastPosition } from "@cartridge/controller";
 
const options: ToastOptions = {
  variant: "error",
  message: "Something went wrong",
  duration: 4000,
  position: "top-right",
};
 
toast(options);

Best Practices

Choose the Right Variant

  • Use error toasts for failures and warnings
  • Use transaction toasts for blockchain operations
  • Use network-switch toasts for chain changes
  • Use achievement toasts for game accomplishments
  • Use quest toasts for quest progression
  • Use marketplace toasts for trading activity

Duration Guidelines

  • Error messages: 5-8 seconds or persistent
  • Success messages: 3-4 seconds
  • Info messages: 4-5 seconds
  • Critical alerts: Persistent (duration: 0)

Positioning Strategy

  • Errors: Top-right or top-center for visibility
  • Success: Bottom-right for less intrusive feedback
  • System notifications: Top-center for importance

Examples in Context

Here's how you might integrate toast notifications in a typical game:

import Controller, { toast } from "@cartridge/controller";
 
const controller = new Controller();
 
// Transaction handling
async function executeGameAction() {
  try {
    const dismiss = toast({
      variant: "transaction",
      status: "confirming",
      label: "Processing move...",
    });
 
    const result = await controller.account.execute(calls);
    
    dismiss(); // Remove confirming toast
    
    toast({
      variant: "transaction", 
      status: "confirmed",
      label: "Move successful!",
      duration: 3000,
    });
    
  } catch (error) {
    toast({
      variant: "error",
      message: `Transaction failed: ${error.message}`,
      duration: 6000,
    });
  }
}
 
// Achievement system
function onLevelUp(level: number, xp: number) {
  toast({
    variant: "achievement",
    title: `Level ${level} Reached!`,
    subtitle: "New abilities unlocked",
    xpAmount: xp,
  });
}
 
// Quest completion
function onQuestComplete(questName: string) {
  toast({
    variant: "quest",
    title: "Quest Completed",
    subtitle: questName,
  });
}

Migration from Other Toast Libraries

If you're currently using libraries like react-hot-toast or sonner, the Cartridge toast system provides similar functionality with game-specific enhancements:

// Before (react-hot-toast)
import toast from 'react-hot-toast';
toast.error('Something went wrong!');
 
// After (Cartridge Controller)
import { toast } from '@cartridge/controller';
toast({
  variant: 'error',
  message: 'Something went wrong!',
});

The main advantages of using the built-in toast system:

  • Game-optimized variants: Purpose-built for gaming scenarios
  • Cross-iframe compatibility: Works seamlessly with Cartridge keychain
  • Consistent theming: Matches your controller preset styling
  • Zero additional dependencies: Included with the controller package