Docs Menu
Docs/Migration/Migrating from SweetAlert2 to toastory
Updated October 2026

Migrating from SweetAlert2 to toastory

Modernize legacy SweetAlert2 alerts, prompts, and modal dialogs with Apple-style frosted glass, zero runtime dependencies, and strict TypeScript safety.

SweetAlert2 has powered modal dialogs for over a decade. However, its legacy jQuery roots, 40 KB+ footprint, global state mutations, and dated skeuomorphic aesthetics make it a heavy fit for modern web apps.

toastory replaces SweetAlert2 with modern Apple frosted glass aesthetics, full WCAG 2.2 AA accessibility, focus trapping, and zero runtime dependencies.

---

Why Modernize SweetAlert2?

  • Modern Frosted Glass Aesthetic: Specular highlight borders and real physical blur instead of flat gray boxes.
  • Micro Bundle Size: Full web bundle under 22 KB gzip (including toasts, dialogs, and sheets), compared to SweetAlert2 alone at 42 KB+.
  • Strict TypeScript Safety: No any types; full autocompletion for 16 input types and return result objects.
  • Integrated Feedback System: One package covers both floating notifications and blocking modal dialogs.

---

Option & Result Mapping Table

SweetAlert2 APItoastory EquivalentNotes
Swal.fire({ title, text, icon })ui.alert({ title, text, tone })Accessible alert with focus trap.
Swal.fire({ showCancelButton: true })ui.confirm({ ... })Two-button confirmation modal.
Swal.fire({ input: 'text' })ui.prompt({ input: 'text' })16 native input types supported.
Swal.fire({ input: 'select', inputOptions })ui.prompt({ input: 'select', options })Dropdown select support.
Swal.queue(steps)ui.steps(stepList)First-class multi-step flow with back button.
Swal.showLoading()ui.loading({ text })Indeterminate or progress overlay.
result.isConfirmedresult.isConfirmedIdentical boolean flag.
result.isDeniedresult.isDeniedIdentical boolean flag.
result.isDismissedresult.isDismissedIdentical boolean flag.
result.valueresult.valueTyped value of prompt input.
result.dismissresult.dismissReason: 'cancel', 'backdrop', 'close', 'esc', 'timer'.
preConfirmpreConfirm: async (val, handle)Async confirmation hook with automatic button spinner.

---

Side-by-Side Implementation Examples

#### 1. Dangerous Destructive Confirmation

typescript
// Before (SweetAlert2)
const result = await Swal.fire({
  title: 'Are you sure?',
  text: 'You will not be able to recover this file!',
  icon: 'warning',
  showCancelButton: true,
  confirmButtonText: 'Yes, delete it!',
  cancelButtonText: 'Cancel',
  confirmButtonColor: '#d33',
});
if (result.isConfirmed) {
  Swal.fire('Deleted!', 'Your file has been deleted.', 'success');
}
typescript
// After (toastory)

const result = await ui.confirm({ title: 'Are you sure?', text: 'You will not be able to recover this file!', tone: 'danger', confirmButton: { label: 'Yes, delete it!' }, cancelButton: { label: 'Cancel' }, });

if (result.isConfirmed) { toast.success('Your file has been deleted.'); } `

---

#### 2. Input Prompt with Validation and Async Lock

typescript
// Before (SweetAlert2)
const { value: email } = await Swal.fire({
  title: 'Input email address',
  input: 'email',
  inputPlaceholder: 'Enter your email',
  inputValidator: (value) => {
    if (!value) return 'You need to write something!';
  },
  showCancelButton: true,
  showLoaderOnConfirm: true,
  preConfirm: async (val) => {
    await sendInvite(val);
  },
});
typescript
// After (toastory)
const res = await ui.prompt({
  title: 'Input email address',
  input: 'email',
  placeholder: 'Enter your email',
  validate: (value) => {
    if (!value) return 'You need to write something!';
    return undefined; // valid
  },
  preConfirm: async (val) => {
    await sendInvite(val as string);
  },

if (res.isConfirmed) { toast.success(Invitation sent to ${res.value}); } `

Want to test these options live?

Launch the interactive playground to experiment with themes, positions, and live generators.

Open in Playground →