A beautiful, responsive, customizable and accessible replacement for JavaScript's popup boxes
—
Auto-close functionality with comprehensive timer controls and progress indication capabilities for creating time-sensitive popups and notifications.
Methods to check timer status and get remaining time information.
/**
* If timer parameter is set, returns number of milliseconds of timer remained
* Otherwise, returns undefined
* @returns Remaining milliseconds or undefined if no timer is set
*/
function getTimerLeft(): number | undefined;
/**
* Check if timer is running. Returns true if timer is running,
* and false if timer is paused/stopped
* If timer parameter isn't set, returns undefined
* @returns Timer running status or undefined if no timer is set
*/
function isTimerRunning(): boolean | undefined;Usage Examples:
// Monitor timer progress
Swal.fire({
title: 'Auto-closing notification',
text: 'This will close automatically',
timer: 5000,
timerProgressBar: true,
didOpen: () => {
const interval = setInterval(() => {
const timeLeft = Swal.getTimerLeft();
if (timeLeft !== undefined) {
console.log(`${Math.ceil(timeLeft / 1000)} seconds remaining`);
} else {
clearInterval(interval);
}
}, 100);
}
});
// Check timer status
if (Swal.isTimerRunning()) {
console.log('Timer is currently running');
} else {
console.log('Timer is paused or not set');
}Methods to control timer execution during popup display.
/**
* Stop timer. Returns number of milliseconds of timer remained
* If timer parameter isn't set, returns undefined
* @returns Remaining milliseconds or undefined if no timer is set
*/
function stopTimer(): number | undefined;
/**
* Resume timer. Returns number of milliseconds of timer remained
* If timer parameter isn't set, returns undefined
* @returns Remaining milliseconds or undefined if no timer is set
*/
function resumeTimer(): number | undefined;
/**
* Toggle timer. Returns number of milliseconds of timer remained
* If timer parameter isn't set, returns undefined
* @returns Remaining milliseconds or undefined if no timer is set
*/
function toggleTimer(): number | undefined;
/**
* Increase timer. Returns number of milliseconds of an updated timer
* If timer parameter isn't set, returns undefined
* @param ms - The number of milliseconds to add to the current timer
* @returns Updated timer milliseconds or undefined if no timer is set
*/
function increaseTimer(ms: number): number | undefined;Usage Examples:
// Interactive timer control
Swal.fire({
title: 'Timer Control Demo',
html: `
<p>This popup will auto-close in 10 seconds</p>
<div style="margin-top: 20px;">
<button id="pause-btn" class="swal2-styled">Pause</button>
<button id="resume-btn" class="swal2-styled">Resume</button>
<button id="add-time-btn" class="swal2-styled">+5s</button>
</div>
`,
timer: 10000,
timerProgressBar: true,
didOpen: () => {
const pauseBtn = document.getElementById('pause-btn');
const resumeBtn = document.getElementById('resume-btn');
const addTimeBtn = document.getElementById('add-time-btn');
pauseBtn.addEventListener('click', () => {
const remaining = Swal.stopTimer();
console.log(`Timer paused with ${remaining}ms remaining`);
});
resumeBtn.addEventListener('click', () => {
const remaining = Swal.resumeTimer();
console.log(`Timer resumed with ${remaining}ms remaining`);
});
addTimeBtn.addEventListener('click', () => {
const newTime = Swal.increaseTimer(5000);
console.log(`Timer increased to ${newTime}ms`);
});
}
});
// Toggle timer on hover
Swal.fire({
title: 'Hover to pause',
text: 'Timer pauses when you hover over this popup',
timer: 8000,
timerProgressBar: true,
didOpen: (popup) => {
popup.addEventListener('mouseenter', () => {
Swal.stopTimer();
});
popup.addEventListener('mouseleave', () => {
Swal.resumeTimer();
});
}
});Timer-related options in SweetAlertOptions:
interface TimerOptions {
/**
* Auto close timer of the popup. Set in ms (milliseconds)
* @default undefined
*/
timer?: number;
/**
* If set to true, the timer will have a progress bar at the bottom of a popup
* Mostly, this feature is useful with toasts
* @default false
*/
timerProgressBar?: boolean;
}// Success toast with timer
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer);
toast.addEventListener('mouseleave', Swal.resumeTimer);
}
});
Toast.fire({
icon: 'success',
title: 'Signed in successfully'
});
// Error toast with longer timer
Toast.fire({
icon: 'error',
title: 'Login failed',
timer: 5000
});// Confirmation with countdown
let timeLeft = 10;
const countdownInterval = setInterval(() => {
timeLeft--;
Swal.update({
html: `This action will be confirmed automatically in ${timeLeft} seconds`,
timer: undefined // Reset timer to prevent conflict
});
if (timeLeft <= 0) {
clearInterval(countdownInterval);
Swal.clickConfirm();
}
}, 1000);
const result = await Swal.fire({
title: 'Auto-confirm',
html: `This action will be confirmed automatically in ${timeLeft} seconds`,
showCancelButton: true,
confirmButtonText: 'Confirm Now',
cancelButtonText: 'Cancel',
allowOutsideClick: false,
willClose: () => {
clearInterval(countdownInterval);
}
});// File upload with timer-based progress
const uploadProgress = (duration: number) => {
return new Promise((resolve) => {
let progress = 0;
const totalSteps = 100;
const stepDuration = duration / totalSteps;
Swal.fire({
title: 'Uploading...',
html: 'Progress: 0%',
timer: duration,
timerProgressBar: true,
allowOutsideClick: false,
didOpen: () => {
const interval = setInterval(() => {
progress++;
Swal.update({
html: `Progress: ${progress}%`
});
if (progress >= totalSteps) {
clearInterval(interval);
Swal.update({
title: 'Upload Complete!',
html: 'Your file has been uploaded successfully',
icon: 'success',
timer: 2000
});
setTimeout(resolve, 2000);
}
}, stepDuration);
}
});
});
};
// Usage
await uploadProgress(5000); // 5 second upload simulation// Adaptive timer based on content length
const showAdaptiveNotification = (message: string) => {
// Calculate reading time: ~200 words per minute, ~5 characters per word
const readingTime = Math.max(3000, (message.length / 5) * 60 / 200 * 1000);
Swal.fire({
title: 'Notification',
text: message,
timer: readingTime,
timerProgressBar: true,
showConfirmButton: false,
didOpen: () => {
console.log(`Auto-closing in ${readingTime}ms based on content length`);
}
});
};
// Short message (3 second minimum)
showAdaptiveNotification('Saved!');
// Long message (calculated based on length)
showAdaptiveNotification('Your changes have been saved successfully. The system has automatically created a backup of your previous version and updated all related references. You can continue working with confidence knowing your data is secure.');// Timer that stops on validation errors
Swal.fire({
title: 'Quick Form',
html: '<input id="quick-input" class="swal2-input" placeholder="Enter something">',
timer: 10000,
timerProgressBar: true,
showConfirmButton: true,
confirmButtonText: 'Submit',
didOpen: () => {
const input = document.getElementById('quick-input');
input.addEventListener('input', (e) => {
const value = e.target.value;
if (value.length > 0) {
// Stop timer when user starts typing
Swal.stopTimer();
} else {
// Resume timer if input is cleared
Swal.resumeTimer();
}
});
},
preConfirm: () => {
const input = document.getElementById('quick-input');
const value = input.value;
if (!value) {
Swal.showValidationMessage('Please enter something');
// Add extra time for user to correct
Swal.increaseTimer(5000);
return false;
}
return value;
}
});// Multi-step process with different timer durations
const runMultiStageProcess = async () => {
// Stage 1: Preparation (3 seconds)
await Swal.fire({
title: 'Preparing...',
text: 'Setting up the process',
timer: 3000,
timerProgressBar: true,
showConfirmButton: false,
allowOutsideClick: false
});
// Stage 2: Processing (8 seconds with dynamic updates)
let stage2Complete = false;
const stage2Promise = new Promise<void>((resolve) => {
let progress = 0;
Swal.fire({
title: 'Processing...',
html: 'Step 1 of 4',
timer: 8000,
timerProgressBar: true,
showConfirmButton: false,
allowOutsideClick: false,
didOpen: () => {
const interval = setInterval(() => {
progress++;
const step = Math.ceil(progress / 20);
Swal.update({
html: `Step ${step} of 4`
});
if (progress >= 80) {
clearInterval(interval);
stage2Complete = true;
resolve();
}
}, 100);
}
});
});
await stage2Promise;
// Stage 3: Completion (2 seconds)
await Swal.fire({
title: 'Complete!',
text: 'Process finished successfully',
icon: 'success',
timer: 2000,
timerProgressBar: true,
showConfirmButton: false
});
};
// Execute the multi-stage process
runMultiStageProcess();// Advanced timer integration with lifecycle events
Swal.fire({
title: 'Event-driven Timer',
text: 'Watch the console for timer events',
timer: 8000,
timerProgressBar: true,
showCancelButton: true,
willOpen: () => {
console.log('Timer will start when popup opens');
},
didOpen: () => {
console.log('Timer started');
// Log timer status every second
const logInterval = setInterval(() => {
const timeLeft = Swal.getTimerLeft();
const isRunning = Swal.isTimerRunning();
console.log(`Timer: ${timeLeft}ms left, running: ${isRunning}`);
if (timeLeft === undefined) {
clearInterval(logInterval);
}
}, 1000);
},
willClose: () => {
console.log('Timer stopped - popup closing');
},
didClose: () => {
console.log('Timer completed or popup was closed');
}
});Install with Tessl CLI
npx tessl i tessl/npm-sweetalert2