solid-sonner

An opinionated toast notification component for Solid, closely tracking the React Sonner API.

Library
npm
v0.3.2
100stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
68/100Good
Development Activity88
Maintenance80
Community32
Maturity52
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
67/100Good
Architecture78
Code Quality62
Innovation72
Learning Curve55

solid-sonner is a SolidJS port of Sonner, the popular React toast library, giving Solid apps the same imperative toast() API, animations, and swipe-to-dismiss behavior without pulling in React. It ships as a single drop-in <Toaster /> component plus a toast() function with success/error/warning/info/loading/promise/custom variants, a useSonner() hook for reading active toasts, and full styling control via classNames, unstyled mode, and Tailwind-friendly overrides.

The project deliberately mirrors upstream Sonner’s behavior and bug fixes release-for-release — its changelog cites the specific upstream commits it ports — so teams already using Sonner in a React codebase can reuse the same mental model and most of the same props when building with Solid.

What You Get

  • Drop-in Toaster component - Mount <Toaster /> once and call toast() anywhere in the tree; no context provider or store wiring required.
  • Full toast type coverage - toast.success, .error, .warning, .info, .loading, .promise, and .custom cover the common notification shapes out of the box.
  • Promise-aware toasts - toast.promise() automatically walks a toast through loading to success/error states, including HTTP-response and Error-aware resolution.
  • Swipe-to-dismiss with configurable directions - Toasts respond to pointer drags with velocity-based thresholds and per-position default swipe directions.
  • Multiple toaster instances - Toasts can be routed to a specific <Toaster id="..." /> via toasterId, useful for a sidebar-scoped toast feed alongside a global one.
  • Unstyled / Tailwind-friendly mode - toastOptions.unstyled plus a full classNames map lets you replace the shipped CSS entirely.

Common Use Cases

  • Form submission feedback - Show a loading toast while a form submits, then update it to success or error in place using the same toast id.
  • Background job / upload progress - Use toast.promise() to reflect a long-running async task’s state without manual toast bookkeeping.
  • Undo flows - Attach an action with a label and onClick to a toast so users can undo a destructive action, Gmail-style.
  • Multi-region notifications - Run a global <Toaster /> plus a secondary scoped <Toaster id="sidebar" /> to separate app-wide alerts from panel-local ones.

Under The Hood

Architecture The library is a single-module port of the React Sonner toast library to SolidJS, contained almost entirely in src/index.tsx alongside a small state.ts observer and a primitives.ts hook. State flows through a class-based Observer (ToastState) acting as a lightweight pub/sub store: toast(), toast.success(), etc. call into ToastState.create()/dismiss(), which publishes plain toast objects to subscribers. The Toaster component subscribes to this observer inside onMount and mirrors incoming toast events into a SolidJS createStore, using produce/reconcile to keep per-toast identity stable across updates. Each visual Toast is rendered by a dedicated child component that owns its own drag/swipe/timer signals, with createEffect-driven auto-dismiss timers gated by page-visibility and hover/interacting state. Positioning is derived from memoized position groupings, and per-toast vertical offset is computed from a shared heights signal array that every Toast writes into on mount and resize. There is no dependency injection or plugin system; the core abstraction is the Observer singleton, and changing its shape would break every toast() call site.

Tech Stack TypeScript plus SolidJS (peer dependency ^1.6.0) is the only runtime dependency; the package ships no other non-peer dependencies and no CSS framework, injecting a plain stylesheet at runtime via a <style data-sonner> tag. The dev workflow runs on Vite and vite-plugin-solid through vite-plus’s vp CLI wrapper (vp pack for building the npm package, vp lint/fmt/check for tooling), with TypeScript providing types. Testing uses Playwright driving a small SolidJS demo app rather than isolated unit tests. Releases are managed with Changesets, and the package is distributed as ESM only, with an exports map exposing a solid condition alongside compiled JS and declaration files.

Code Quality The only tests are Playwright end-to-end specs that click through a demo app’s data-testid buttons and assert on rendered toast DOM — there are no isolated unit tests of the Observer logic in state.ts, though the e2e coverage does exercise dismiss/promise/loading/custom toast flows. Source is fully typed TypeScript with a complete public type surface for toast and toaster props, and inline comments explain non-obvious ordering, such as why pending dismissals are tracked and why history trimming only drops already-dismissed toasts. Linting and formatting are delegated to the vp CLI, a typecheck script runs the compiler in no-emit mode, and CI runs via GitHub Actions.

API Design The library’s main achievement is faithfully reproducing React Sonner’s full imperative API — toast(), toast.success/error/promise/custom, useSonner() — on top of Solid’s fine-grained reactivity instead of React’s re-render model, including edge cases like reusing a dismissed toast’s id, updating a loading toast in place, and swipe-to-dismiss physics with velocity-based thresholds, several of which are called out explicitly in the changelog as ports of upstream bug fixes. Getting started requires only rendering <Toaster /> once and calling toast() from anywhere, with no configuration; the API intentionally mirrors Sonner’s so migrating a React app’s toast usage to Solid is close to a drop-in replacement. It does not introduce new toast concepts beyond what Sonner already established — its value is DX parity and low adoption friction for teams moving between the two frameworks.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search