Developer Docs
Quick reference guides with props tables, usage examples, and best practices for rapid development
ConfirmModal
ConfirmModal
A styled confirmation dialog that replaces browser's native confirm(). Provides two usage patterns: Component pattern for full state control, and Promise pattern for simple async/await workflows.
Quick Example
Danger
Async/Await
🔧 Props
Complete configuration options for ConfirmModal component and showConfirm function.
| Prop | Type | Default | Description |
|---|---|---|---|
| isOpen | van.State<boolean> | false | Whether the modal is visible (use van.state for reactivity) |
| title | string | 'Confirm Action' | Modal title text |
| message | string | 'Are you sure?' | Confirmation message body |
| confirmText | string | () => string | 'Confirm' | Confirm button text (can be reactive function for loading states) |
| cancelText | string | 'Cancel' | Cancel button text |
| variant | string | 'danger' | Visual variant: 'danger', 'warning', 'info' |
| onConfirm | Function | undefined | Callback when user confirms |
| onCancel | Function | undefined | Callback when user cancels or closes |
💻 Component Pattern
Use when you need full control over modal state and loading states:
Basic Usage
const showModal = van.state(false);
Button({
onclick: () => showModal.val = true
}, 'Delete Item'),
() => showModal.val ? ConfirmModal({
isOpen: showModal,
title: 'Delete Item',
message: 'This action cannot be undone.',
variant: 'danger',
onConfirm: () => {
deleteItem();
showModal.val = false;
},
onCancel: () => showModal.val = false
}) : ''With Loading State
const showModal = van.state(false);
const isDeleting = van.state(false);
const handleDelete = async () => {
isDeleting.val = true;
await deleteItem();
isDeleting.val = false;
showModal.val = false;
showToast('Deleted successfully', 'success');
};
ConfirmModal({
isOpen: showModal,
title: 'Delete Service',
message: 'This will permanently delete the service.',
confirmText: () => isDeleting.val ? 'Deleting...' : 'Delete',
variant: 'danger',
onConfirm: handleDelete,
onCancel: () => showModal.val = false
})🔮 Promise Pattern (showConfirm)
Use for simple async/await workflows without managing state:
Basic Usage
import { showConfirm } from 'shared-components/ui/ConfirmModal.js';
const handleDelete = async () => {
const confirmed = await showConfirm({
title: 'Delete Service',
message: 'Are you sure?',
variant: 'danger'
});
if (confirmed) {
await deleteService();
showToast('Deleted', 'success');
}
};With Custom Text
const confirmed = await showConfirm({
title: 'Leave Page',
message: 'You have unsaved changes. Leave anyway?',
confirmText: 'Leave',
cancelText: 'Stay',
variant: 'warning'
});Promise Pattern Config
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | 'Confirm Action' | Modal title |
| message | string | 'Are you sure?' | Message body |
| confirmText | string | 'Confirm' | Confirm button text |
| cancelText | string | 'Cancel' | Cancel button text |
| variant | string | 'danger' | 'danger', 'warning', or 'info' |
Returns: Promise<boolean> - Resolves to true if confirmed, false if cancelled
🎨 Variants
Three semantic variants for different confirmation scenarios with automatic icons and colors.
Danger (Default)
For destructive, irreversible actions (delete, remove, destroy)
ConfirmModal({
variant: 'danger',
title: 'Delete Account',
message: 'This action cannot be undone.'
})Warning
For reversible but significant actions (cancel subscription, leave page)
ConfirmModal({
variant: 'warning',
title: 'Leave Page',
message: 'You have unsaved changes.'
})Info
For neutral confirmations (mark as read, enable feature)
ConfirmModal({
variant: 'info',
title: 'Enable Notifications',
message: 'Would you like to receive updates?'
})⚡️ Best Practices
✓ Do This
✓Use "danger" for Irreversible Actions
- Apply danger variant for deletions and permanent destructive actions
✓Use "warning" for Reversible Actions
- Use warning variant for actions that can be undone or reverted
✓Use Promise Pattern for Simple Workflows
- Leverage Promise-based showConfirm for clean async/await confirmation flows
✓Use Component Pattern for Loading States
- Use ConfirmModal component directly when you need loading states and state control
✓Show Loading States
- Display loading feedback during async operations for better UX
✓Use Descriptive Confirm Text
- Use specific button text like "Delete Account" instead of generic "OK"
✓Close Modal After Action
- Always close the modal after successful action completion
✗ Avoid This
✗Don't Overuse Confirmations
- Avoid showing confirmations for every action; causes confirmation fatigue
✗Don't Write Vague Messages
- Never use generic messages like "Are you sure?"; be specific about what will happen
✗Don't Forget to Close Modal
- Always close the modal after action; leaving it open confuses users
✗Don't Mix Patterns
- Choose either Component or Promise pattern; don't mix both in same flow
✗Don't Use Generic Button Text
- Avoid generic "OK" button text; use action-specific labels
✗Don't Skip Loading States
- Always show loading feedback for operations that take time
✗Don't Misuse Variants
- Never use info variant for dangerous destructive actions; use danger instead
🤔 When to Use Each Pattern
Use Component Pattern When:
✓You need loading states (button shows "Deleting...")
✓You need custom state management
✓You need to disable buttons during async operations
✓You need reactive button text
✓The modal is part of a larger component with complex state
Use Promise Pattern When:
✓You need simple yes/no confirmation
✓You want clean async/await code
✓You don't need loading states
✓Action completes quickly
✓You want minimal code
✨ Key Features
⭑Three Semantic Variants
- Danger, warning, and info variants with automatic icons and semantic colors
⭑Two Usage Patterns
- Component pattern for state control, Promise pattern for simple async/await workflows
⭑Loading State Support
- Reactive button text for async operations ("Deleting...", "Processing...")
⭑Full Accessibility
- Built on Modal component with keyboard navigation, focus management, and ARIA support
⭑Auto Cleanup
- Promise pattern automatically removes DOM elements after animation completes
⭑Glass Morphism Design
- Inherits Modal styling with glass effect, backdrop blur, and smooth animations
⭑Customizable Button Text
- Configure confirmText and cancelText for action-specific button labels
⭑Automatic Icon Selection
- Icons automatically match variant (trash for danger, warning triangle, info circle)
💡 Common Use Cases
Real-world examples showing both Component and Promise patterns for common confirmation scenarios.
1. Delete Confirmation
const handleDelete = async () => {
const confirmed = await showConfirm({
title: 'Delete Service',
message: 'This will permanently delete the service and all its data.',
confirmText: 'Delete Service',
variant: 'danger'
});
if (confirmed) {
await deleteService(serviceId);
showToast('Service deleted', 'success');
router.navigate('/services');
}
};2. Leave Page with Unsaved Changes
const handleLeave = async () => {
if (hasUnsavedChanges.val) {
const confirmed = await showConfirm({
title: 'Leave Page',
message: 'You have unsaved changes. Leave anyway?',
confirmText: 'Leave',
cancelText: 'Stay',
variant: 'warning'
});
if (!confirmed) return;
}
router.navigate('/dashboard');
};3. Deactivate Account
const showDeactivateModal = van.state(false);
const isDeactivating = van.state(false);
const handleDeactivate = async () => {
isDeactivating.val = true;
await deactivateAccount();
isDeactivating.val = false;
showDeactivateModal.val = false;
showToast('Account deactivated', 'success');
router.navigate('/goodbye');
};
ConfirmModal({
isOpen: showDeactivateModal,
title: 'Deactivate Account',
message: 'Your account will be deactivated. You can reactivate it anytime.',
confirmText: () => isDeactivating.val ? 'Deactivating...' : 'Deactivate',
variant: 'warning',
onConfirm: handleDeactivate,
onCancel: () => showDeactivateModal.val = false
})4. Bulk Actions
const handleBulkDelete = async () => {
const count = selectedItems.val.length;
const confirmed = await showConfirm({
title: `Delete ${count} Items`,
message: `This will permanently delete ${count} selected items.`,
confirmText: `Delete ${count} Items`,
variant: 'danger'
});
if (confirmed) {
await bulkDelete(selectedItems.val);
showToast(`${count} items deleted`, 'success');
selectedItems.val = [];
}
};5. Enable Feature
const handleEnableNotifications = async () => {
const confirmed = await showConfirm({
title: 'Enable Notifications',
message: 'Get notified about new services and updates in your area.',
confirmText: 'Enable',
cancelText: 'Not Now',
variant: 'info'
});
if (confirmed) {
await enableNotifications();
showToast('Notifications enabled', 'success');
}
};🔗 Integration Patterns
Best practices for integrating ConfirmModal with other components and application patterns.
With Toast (Feedback)
const handleDelete = async () => {
const confirmed = await showConfirm({
title: 'Delete Item',
message: 'Are you sure?',
variant: 'danger'
});
if (confirmed) {
await deleteItem();
showToast('Item deleted successfully', 'success');
} else {
showToast('Deletion cancelled', 'info');
}
};With Router (Navigation)
const handleLogout = async () => {
const confirmed = await showConfirm({
title: 'Logout',
message: 'Are you sure you want to logout?',
variant: 'info'
});
if (confirmed) {
await logout();
router.navigate('/auth/signin');
}
};With Forms (Discard Changes)
const handleCancel = async () => {
if (form.isDirty.val) {
const confirmed = await showConfirm({
title: 'Discard Changes',
message: 'You have unsaved changes. Discard them?',
confirmText: 'Discard',
cancelText: 'Keep Editing',
variant: 'warning'
});
if (!confirmed) return;
}
router.navigate('/services');
};Explore More Components
Browse other component categories