AI Toast
AI Toast provides event-driven notifications for AI-generated insights and status updates. It’s built on top of AiBanner
and uses a small internal store to manage multiple toasts with stacking, updates, and (optional) auto-dismiss.
Loading...
Overview
Resources
Install
yarn add @camp/ai-banner
API usage
Recommended (Controller API)
Use this in application code. It’s the simplest, safest way to create, update, and dismiss a toast.
import { toast, ToastDurationPreset } from '@camp/ai-banner';
const controller = toast({
title: 'AI Analysis In Progress',
description: 'Processing your campaign data...',
appearance: 'info',
duration: 0, // persistent until you update/dismiss
});
// Later…
controller.update({
title: 'Analysis Complete',
description: 'Your AI-powered insights are ready.',
appearance: 'success',
duration: ToastDurationPreset.Standard,
});
// When done…
controller.dismiss();
// You can also read the id if needed:
const { id } = controller;
- Use when: Creating toasts from components, hooks, and normal UI flows.
- Why: Keeps lifecycle localized without tracking ids across modules.
Advanced (Store API)
Low-level functions for cross-boundary scenarios (outside React, background jobs, or global cleanup).
import {
showToast,
updateToast,
dismissToast,
clearToasts,
ToastDurationPreset,
} from '@camp/ai-banner';
// Create and capture the id
const id = showToast({
title: 'AI Processing Started',
description: 'Analyzing data…',
appearance: 'info',
duration: 0,
});
// Update later (requires the id)
updateToast(id, {
title: 'Processing Complete',
description: 'AI analysis finished successfully.',
appearance: 'success',
duration: ToastDurationPreset.Standard,
});
// Dismiss specific or clear all
dismissToast(id);
clearToasts();
Variations
Basic Toast Creation
import { toast, ToastDurationPreset } from '@camp/ai-banner';
toast({
title: 'Optimization Opportunity Detected',
description: 'AI found ways to improve your email engagement.',
appearance: 'educational',
duration: ToastDurationPreset.Long,
});
toast({
title: 'Processing AI Recommendations',
description: 'Analyzing your data to generate insights...',
appearance: 'info',
duration: 0, // persistent until dismissed
});
Updating Toast Content
import { toast, ToastDurationPreset } from '@camp/ai-banner';
const controller = toast({
title: 'AI Analysis In Progress',
description: 'Processing your campaign data...',
appearance: 'info',
duration: 0,
});
setTimeout(() => {
controller.update({
title: 'Analysis Complete',
description: 'Your AI-powered insights are ready.',
appearance: 'success',
duration: ToastDurationPreset.Standard,
});
}, 3000);
Multiple Toasts
import { toast, ToastDurationPreset } from '@camp/ai-banner';
const segmentAnalysis = toast({
title: 'Analyzing Customer Segments',
description: 'AI is processing your audience data...',
appearance: 'info',
duration: 0,
});
const campaignOptimization = toast({
title: 'Optimizing Campaign Performance',
description: 'AI is analyzing engagement patterns...',
appearance: 'info',
duration: 0,
});
segmentAnalysis.update({
title: 'Segment Analysis Complete',
description: 'Found 3 high-value customer segments.',
appearance: 'success',
duration: ToastDurationPreset.Standard,
});
Render React Nodes
Toast title
and description
accept React nodes, allowing you to embed interactive components like progress bars, links, or formatted content.
import { toast } from '@camp/ai-banner';
import { ProgressBar } from '@camp/progress-bar';
import { useState, useEffect, useRef } from 'react';
const UploadComponent = () => {
const [progress, setProgress] = useState(1);
const controllerRef = useRef<ReturnType<typeof toast> | null>(null);
useEffect(() => {
// Create toast with initial progress bar
controllerRef.current = toast({
title: 'Uploading…',
description: (
<div style={{ width: 320, marginTop: 8 }}>
<ProgressBar value={progress} ariaLabel="Upload progress" showValue />
</div>
),
appearance: 'info',
duration: 0, // persistent while uploading
});
// Simulate progress to 100%
const timer = setTimeout(() => setProgress(100), 1000);
return () => clearTimeout(timer);
}, []);
useEffect(() => {
const controller = controllerRef.current;
if (!controller) return;
// Update progress bar in real-time
controller.update({
description: (
<div style={{ width: 320, marginTop: 8 }}>
<ProgressBar
value={progress}
appearance={progress >= 100 ? 'success' : 'default'}
ariaLabel="Upload progress"
showValue
/>
</div>
),
});
// Switch to success state when complete
if (progress >= 100) {
controller.update({
title: 'Upload complete',
appearance: 'success',
duration: 3000,
});
}
}, [progress]);
return <Toaster />;
};
Duration Presets
import { toast, ToastDurationPreset } from '@camp/ai-banner';
toast({ title: 'Settings Updated', appearance: 'success', duration: ToastDurationPreset.Short });
toast({
title: 'AI Analysis Complete',
description: 'Your insights are ready to view.',
appearance: 'info',
duration: ToastDurationPreset.Standard,
});
toast({
title: 'Important AI Insight',
description: 'Critical performance issue detected.',
appearance: 'warning',
duration: ToastDurationPreset.Long,
});
toast({
title: 'Custom Timing',
description: 'Dismisses after 5 seconds.',
appearance: 'info',
duration: 5000,
});
toast({
title: 'Action Required',
description: 'Please review these AI recommendations.',
appearance: 'warning',
duration: 0, // persistent
});
Migration: legacy Toast → AI Toast
This shows how to move from the old Toaster
+ createToast
API to the new AiToaster
+ toast
controller API.
Before (legacy)
import { createToast } from '@activecampaign/camp-components-toast';
const MyComponent = () => {
const notify = () => {
createToast({
title: 'Toaster Banner Title',
description: 'This is a Toast notification, and it accepts all the same props as Banner.',
});
};
return <Button onClick={notify}>Create Toast</Button>;
};
After (AI Toast, recommended)
import { AiToaster, toast, ToastDurationPreset } from '@camp/ai-banner';
import { AiButton } from '@camp/ai-button';
const actions = () => (
<div style={{ display: 'flex', gap: 8 }}>
<AiButton appearance="secondary" size="small">
Action
</AiButton>
</div>
);
export const example = () => {
const create = () => {
toast({
title: 'Toaster Banner Title',
description: 'This is a Toast notification, and it accepts all the same props as Banner.',
appearance: 'info',
duration: ToastDurationPreset.Standard,
renderActions: actions, // replaces legacy `actions`
});
};
return (
<>
<AiButton onClick={create}>Create Toast</AiButton>
<AiToaster headerOffset="3em" />
</>
);
};
Notes
actions
→renderActions
(function returning UI).toastDismissButtonLabel
isn’t currently configurable in AI Toast.- For advanced usage (outside component scope), prefer the Store API:
showToast
,updateToast
,dismissToast
,clearToasts
.
Usage guidelines
- Use toasts for AI processing, insights, or recommendations.
- Start with informational appearance during processing; update to success/warning/destructive as outcomes are known.
- Use persistent toasts (
duration: 0
) for items that require attention or action. - Keep content concise and actionable; prefer presets for consistent timing.
- Clean up toasts on navigation if they’re no longer relevant.
- Prefer updating an existing toast over creating many similar toasts.
Accessibility
- Toasts render with
role="alert"
(fromAiBanner
). - Dismiss buttons use an accessible label.
- Action buttons are reachable via normal tab navigation.
Setup
Render AiToaster
once near your app root. Toasts appear top-right; you can offset for a fixed header.
import { AiToaster } from '@camp/ai-banner';
function App() {
return (
<>
{/* …your app… */}
<AiToaster headerOffset="60px" />
</>
);
}