Advanced Examples
Advanced patterns and complex use cases for Nuxt Notify.
Queue Management
Sequential Notifications
Show notifications one after another:
vue
<script setup>
const toast = useToast();
async function processQueue() {
const steps = [
{ title: "Initializing", description: "Preparing data..." },
{ title: "Processing", description: "Analyzing files..." },
{ title: "Finalizing", description: "Saving results..." },
{ title: "Complete", description: "All done!" },
];
for (let i = 0; i < steps.length; i++) {
await new Promise((resolve) => setTimeout(resolve, 2000));
const isLast = i === steps.length - 1;
toast.add({
type: isLast ? "success" : "info",
title: steps[i].title,
description: steps[i].description,
showProgress: true,
duration: 3000,
});
}
}
</script>
Batch Operations
Handle multiple operations with progress:
vue
<script setup>
const toast = useToast();
async function batchDelete(items) {
let completed = 0;
let failed = 0;
const total = items.length;
// Show initial progress
const progressToast = toast.info(
"Deleting Items",
`Processing 0 of ${total}...`,
{ duration: Infinity, showProgress: false }
);
for (const item of items) {
try {
await api.delete(item.id);
completed++;
} catch (error) {
failed++;
}
// Update progress (in real app, you'd update the existing toast)
if (completed + failed < total) {
toast.info(
"Deleting Items",
`Processing ${completed + failed} of ${total}...`,
{ duration: Infinity }
);
}
}
// Show final result
toast.clear();
if (failed === 0) {
toast.success(
"Batch Delete Complete",
`${completed} items deleted successfully`
);
} else {
toast.warning(
"Batch Delete Complete",
`${completed} succeeded, ${failed} failed`,
{
actions: [
{ label: "View Errors", onClick: () => showErrors() },
{ label: "Retry Failed", onClick: () => retryFailed() },
],
}
);
}
}
</script>
Real-Time Updates
Live Notifications
Handle real-time events:
vue
<script setup>
const toast = useToast();
// WebSocket or SSE connection
const ws = useWebSocket("wss://api.example.com/notifications");
ws.onMessage((event) => {
const notification = JSON.parse(event.data);
switch (notification.type) {
case "mention":
toast.add({
type: "info",
title: `${notification.user.name} mentioned you`,
description: notification.message,
avatar: {
type: "image",
src: notification.user.avatar,
},
actions: [
{ label: "Reply", onClick: () => handleReply(notification.id) },
{ label: "View", onClick: () => navigateTo(notification.url) },
],
});
break;
case "task_assigned":
toast.warning("New Task Assigned", notification.task.title, {
showProgress: true,
actions: [
{ label: "View Task", onClick: () => openTask(notification.task.id) },
],
});
break;
case "update":
toast.success(notification.title, notification.message);
break;
}
});
</script>
Status Updates
Track ongoing operations:
vue
<script setup>
const toast = useToast();
const operationStatus = ref("idle");
async function longRunningOperation() {
operationStatus.value = "starting";
toast.info("Starting Process", "Initializing...", {
showProgress: true,
duration: 5000,
});
try {
// Step 1
operationStatus.value = "step1";
await performStep1();
toast.info("Progress Update", "Step 1 complete", { duration: 2000 });
// Step 2
operationStatus.value = "step2";
await performStep2();
toast.info("Progress Update", "Step 2 complete", { duration: 2000 });
// Step 3
operationStatus.value = "step3";
await performStep3();
toast.success("Process Complete", "All steps finished successfully");
operationStatus.value = "complete";
} catch (error) {
operationStatus.value = "error";
toast.error("Process Failed", error.message);
}
}
</script>
Undo/Redo Pattern
Undo Delete
Implement undo functionality:
vue
<script setup>
const toast = useToast();
const deletedItems = ref([]);
function deleteItem(item) {
// Store item for potential undo
deletedItems.value.push(item);
// Soft delete
item.deleted = true;
toast.add({
type: "success",
title: "Item Deleted",
description: item.name,
duration: 5000,
actions: [
{
label: "Undo",
onClick: () => {
// Restore item
item.deleted = false;
deletedItems.value = deletedItems.value.filter(
(i) => i.id !== item.id
);
toast.info("Restored", `${item.name} has been restored`);
},
},
],
});
// Permanently delete after 5 seconds
setTimeout(() => {
if (item.deleted) {
api.permanentlyDelete(item.id);
deletedItems.value = deletedItems.value.filter((i) => i.id !== item.id);
}
}, 5000);
}
</script>
Bulk Undo
Undo multiple operations:
vue
<script setup>
const toast = useToast();
const operationHistory = ref([]);
function bulkDelete(items) {
const operation = {
type: "bulk_delete",
items: items,
timestamp: Date.now(),
};
operationHistory.value.push(operation);
// Perform deletion
items.forEach((item) => (item.deleted = true));
toast.warning("Bulk Delete", `${items.length} items deleted`, {
actions: [
{
label: "Undo All",
onClick: () => {
items.forEach((item) => (item.deleted = false));
operationHistory.value = operationHistory.value.filter(
(op) => op !== operation
);
toast.success("Restored", `${items.length} items restored`);
},
},
],
duration: 10000,
});
}
</script>
Context-Aware Notifications
Position Based on Context
Change position based on UI context:
vue
<script setup>
const toast = useToast();
const route = useRoute();
function showContextualToast(message) {
// Different positions for different pages
const positions = {
"/dashboard": "top-right",
"/editor": "bottom-right", // Don't block editor toolbar
"/chat": "top-center", // Centered for chat
"/settings": "top-left",
};
const position = positions[route.path] || "top-right";
toast.success(message.title, message.description, {
position,
duration: 3000,
});
}
</script>
Conditional Formatting
Style based on conditions:
vue
<script setup>
const toast = useToast();
function notifyUser(notification) {
const isUrgent = notification.priority === "high";
const isFromAdmin = notification.sender.role === "admin";
toast.add({
type: isUrgent ? "warning" : "info",
title: notification.title,
description: notification.message,
duration: isUrgent ? 10000 : 5000,
showProgress: isUrgent,
avatar: notification.sender.avatar,
ui: {
root: isUrgent ? "ring-2 ring-amber-500" : undefined,
title: isFromAdmin ? "font-bold text-primary-600" : undefined,
},
actions: isUrgent
? [{ label: "View Now", onClick: () => handleUrgent(notification) }]
: undefined,
});
}
</script>
Permission Requests
Request User Action
Ask for permissions with context:
vue
<script setup>
const toast = useToast();
function requestNotificationPermission() {
toast.add({
type: "info",
title: "Enable Notifications",
description: "Get notified about important updates and messages",
duration: Infinity,
icon: "i-lucide-bell",
actions: [
{
label: "Enable",
onClick: async () => {
const permission = await Notification.requestPermission();
if (permission === "granted") {
toast.success(
"Notifications Enabled",
"You'll now receive updates"
);
} else {
toast.warning(
"Notifications Blocked",
"You can enable them in settings"
);
}
},
},
{
label: "Not Now",
onClick: () => {
toast.clear();
// Ask again later
setTimeout(() => requestNotificationPermission(), 86400000); // 24 hours
},
},
],
});
}
</script>
Multi-Step Processes
Wizard Progress
Show progress through multi-step forms:
vue
<script setup>
const toast = useToast();
const currentStep = ref(1);
const totalSteps = 5;
function completeStep(stepNumber) {
currentStep.value = stepNumber + 1;
if (stepNumber < totalSteps) {
toast.success(
`Step ${stepNumber} Complete`,
`Progress: ${stepNumber}/${totalSteps}`,
{
showProgress: true,
duration: 2000,
position: "bottom-right",
}
);
} else {
toast.success("All Steps Complete!", "Your setup is finished", {
actions: [
{ label: "Get Started", onClick: () => navigateTo("/dashboard") },
],
duration: 5000,
});
}
}
</script>
Error Recovery
Retry with Exponential Backoff
Handle network errors gracefully:
vue
<script setup>
const toast = useToast();
async function retryableRequest(fn, maxRetries = 3) {
let retries = 0;
while (retries < maxRetries) {
try {
return await fn();
} catch (error) {
retries++;
if (retries < maxRetries) {
const delay = Math.pow(2, retries) * 1000;
toast.warning(
"Request Failed",
`Retrying in ${delay / 1000} seconds... (${retries}/${maxRetries})`,
{
showProgress: true,
duration: delay,
actions: [
{
label: "Cancel",
onClick: () => {
throw new Error("Cancelled by user");
},
},
],
}
);
await new Promise((resolve) => setTimeout(resolve, delay));
} else {
toast.error(
"Request Failed",
"Maximum retries reached. Please try again later.",
{
actions: [
{
label: "Retry Now",
onClick: () => retryableRequest(fn, maxRetries),
},
],
}
);
throw error;
}
}
}
}
</script>
