Open-source project
sweetalert2/sweetalert2 avatar
sweetalert2/sweetalert2

SweetAlert2: replacing window.alert with a dialog you can actually style

✨ A beautiful, responsive, highly customizable and accessible (WAI-ARIA) replacement for JavaScript's popup boxes. Zero dependencies. 🇺🇦🇪🇺

18,101 stars1,620 forksJavaScriptMIT

At a glance

What is it?
sweetalert2 is a zero-dependency JavaScript library that swaps the browser's built-in alert, confirm and prompt boxes for styled, keyboard-accessible dialogs. The README is mostly a sponsor wall, so the real documentation lives on sweetalert2.github.io and in the TypeScript definitions.
Who is it for?
SweetAlert2 earns its place in any project that has outgrown `window.confirm` and does not want to hand-write a focus trap, a backdrop and an escape-key handler. The runtime has no dependencies, which is the deciding factor for a library that loads on every page, and the accessibility work is already done rather than left to you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 24 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the library replaces and why that matters

The pitch in the README is a replacement for JavaScript's popup boxes, with the qualifiers that it is responsive, customizable and accessible through WAI-ARIA, and that it has zero dependencies. The last claim is the one worth checking against the manifest, because it is easy to confuse a dependency-free runtime with a dependency-free build.

The package manifest supports the claim at runtime. It declares no `dependencies` block at all. What it does carry is a long `devDependencies` list for building: Babel and its preset, the Rollup plugins with terser, Cypress, Playwright's webkit browser, Sass, Stylelint, Vite, zx and a pinned TypeScript at 4.8.4. The manifest even carries a comment next to that TypeScript pin explaining that it must not be upgraded because the tests verify types against the very first release at or above 4.8.4. That is a deliberate compatibility floor for consumers who are on old TypeScript, and it is the kind of detail that tells you the project thinks about its dependents.

So the shipped artifact pulls in nothing at runtime, and the project itself is built with a large toolchain. Both statements are true and the difference matters when you audit a bundle.

Three build outputs and where your import comes from

The manifest points at three entry points, and picking the wrong one is the most common packaging mistake.

json
  "main": "dist/sweetalert2.all.js",
  "browser": "dist/sweetalert2.all.js",
  "module": "dist/sweetalert2.esm.all.js",
  "types": "sweetalert2.d.ts",

`main` and `browser` both point at the bundled build, while `module` points at the ESM build, so a bundler that understands `module` will pick the ESM file and a CommonJS consumer will get the bundle. Types come from a hand-maintained `sweetalert2.d.ts` shipped at the package root rather than generated at build time, and the published `files` array is short: `dist`, `src`, `themes` and `sweetalert2.d.ts`. Shipping `src` matters if you want to read the implementation, and shipping `themes` means the default styling ships with the package.

The version in the manifest is 11.26.25, matching the most recent release tag on GitHub, which was published on 2026-05-23. The number is high for a popup library and reflects a long-lived project rather than a frequently breaking one, since releases are mostly bug fixes.

Accessibility is a feature, and the release notes show the work

An alert dialog that is not accessible is worse than the native one, because it looks finished while trapping nobody. The WAI-ARIA claim is the substantive part of this library's pitch, and the recent release history backs it up with the kind of small fixes that only matter when someone is testing with a keyboard and a screen reader.

Release v11.26.24, published on 2026-03-20, fixes tab navigation with an iframe in Firefox. That is a narrow bug, and it is narrow in the way accessibility bugs tend to be: the dialog worked, but focus could end up somewhere unhelpful. The release before it, v11.26.25 on 2026-05-23, fixes icon animation in Firefox. And v11.26.23 on 2026-03-16 is a refactor that simplifies unnecessarily complex code, which suggests the team is willing to restructure for clarity rather than only adding features.

The repository layout backs the claim with testing infrastructure rather than assertions. Alongside `src/` and `test/` there are Cypress and Playwright configurations, meaning dialogs get exercised in real browsers, which is the only way to verify focus order and keyboard behaviour honestly. `release.config.js` suggests releases are automated rather than hand-cut.

For a team with accessibility obligations, this is the part of the library that justifies its place over a hand-rolled modal, and it is the part the changelog keeps quietly repairing.

The README is a sponsor page, so plan your reading accordingly

This is the most unusual thing about the project and any reader should know it before forming an opinion. The README opens with a logo, the tagline, and a row of links to Installation, Usage, Examples, a recipe gallery, and separate repositories for React, Angular and Laravel integration. Then it becomes a sponsorship page: a discount link for a web host, tables of sponsor logos, a section for NSFW sponsors, and a contact address for sponsorship questions.

None of that is a criticism of the project. Sponsorship is how a maintainer funds work on an MIT licensed library that millions of pages load. But the practical consequence is that the front page of the repository contains no usage documentation, no API reference and no accessibility guidance, so an evaluation that stops at the README will find almost nothing to evaluate.

What to read instead is all linked from that top row. Installation and usage are on sweetalert2.github.io, the examples are on the same site, and the recipe gallery covers framework-specific patterns. The API reference effectively lives in `sweetalert2.d.ts` in the repository, which is unusually complete because the types are hand-written. The tree also carries `CHANGELOG.md`, `SECURITY.md` and `SPONSORS.md`, so a vulnerability report has a documented destination, which is more than many projects of this size offer.

Framework wrappers are separate downloads, not part of the core

The related searches around this library cluster on framework names, React and Angular and Laravel among them, and the reason is visible in the README's link row: each integration lives in its own repository. SweetAlert2 core is plain JavaScript with no framework opinion, and the wrappers are separate packages maintained separately.

That separation has real consequences. The React wrapper is what handles rendering the dialog through a React component tree rather than imperatively, and Angular has its own wrapper because Angular's change detection and zone behaviour interact badly with direct DOM manipulation. Laravel integration is a different kind of thing again, living on the server side. Each of these versions on its own schedule, so a project can end up with a current core and a stale wrapper, or the reverse.

The alternative to a wrapper is calling the library directly, which works and is what the core is designed for, but it means your dialog is outside your component tree. In React that produces the familiar problem of state living in a module-level variable rather than in your app, and wrapping it is the usual answer.

The practical check before adopting is to look at the wrapper's own recent releases and its peer dependency range rather than assuming it tracks the core version. The core being at 11.x tells you nothing about whether the React wrapper is current.

Where a native dialog is still the better answer

A library that replaces `alert()` is worth questioning when the use case is a confirmation dialog that nobody reads. The native boxes are ugly, but they are synchronous, they block, and they cannot be styled, which are exactly the reasons to replace them. They are also free, require no bundle weight, and cannot introduce a focus bug.

There is a category where the native call is the right tool. A developer-only error that halts work and needs acknowledging before anything else happens is a reasonable `alert()`. So is anything inside a build script or a test harness where no human is looking. Reaching for a styled dialog there adds a dependency and a failure mode for no reader.

There is also a category where SweetAlert2 is the wrong tool. Toasts and transient notifications are not dialogs; they do not want a backdrop, they do not want to trap focus, and they should not queue behind a modal. If the requirement is a stack of non-blocking notifications, a toast library fits the shape better. SweetAlert2's topics list includes `toast` and `notifications`, so the project is used that way in practice, but a modal dialog is a heavy instrument for a message nobody needs to dismiss.

The honest framing is that this library is at its best replacing confirm and prompt dialogs in a real application, and at its worst used as a general-purpose notification system. Its zero-dependency runtime makes that second case cheap to justify on paper, which is exactly why it happens.

Editorial conclusion

SweetAlert2 earns its place in any project that has outgrown `window.confirm` and does not want to hand-write a focus trap, a backdrop and an escape-key handler. The runtime has no dependencies, which is the deciding factor for a library that loads on every page, and the accessibility work is already done rather than left to you. Check two things before committing: whether your framework wrapper is still maintained, since the README links separate React, Angular and Laravel packages that version independently, and whether you need animations, because motion is the feature most likely to be dropped when someone prefers reduced motion. Start by replacing one native `alert()` in a non-critical path, then read the configuration options on the docs site rather than the front page.

Frequently asked questions

What is SweetAlert2?

SweetAlert2 is a JavaScript library described as a responsive, customizable and accessible replacement for the browser's built-in popup boxes, with zero runtime dependencies. It can be used as a library, imported from a CDN, or through separate framework wrapper packages for React, Angular and Laravel.

How to use sweetalert2 in React?

SweetAlert2 core is plain JavaScript and does not include a React binding. The README links a separate React repository, sweetalert2-react-content, which renders dialog content as React components. That wrapper versions independently of the core package, so check its own release history rather than the core version.

What are some alternatives to SweetAlert2?

The project's own documentation points to a recipe gallery for framework-specific patterns, and the alternatives in that space fall into two groups: other styled dialog libraries, and toast libraries for non-blocking notifications. The repository's topics include toast and notifications, but a modal dialog is a poor fit for transient messages that need no dismissal.

How do I use SweetAlert in HTML?

Add the library to a plain HTML page as a script, then call its interface in place of a native alert or confirm. The installation and usage steps are on the project's documentation site, linked from the README, which is mostly a sponsorship page rather than usage documentation.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. sweetalert2/sweetalert2 on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sweetalert2-sweetalert2.svg)](https://hysenlabs.com/projects/sweetalert2-sweetalert2)