Skip to content

Notifications · Open source

Laravel Sonner

Sonner toast notifications for Laravel, sent from PHP and shown without React.

Laravel 12 and 13 PHP 8.3+ v1.0.0 Free · MIT
Laravel Sonner: Sonner toast notifications for Laravel, sent from PHP and shown without React.

What it solves

Sonner is the toast library behind shadcn/ui, but it is a React component, so a Blade or Livewire app cannot use it directly.

Call toast() in a controller or Livewire action and put <x-sonner /> in your layout. A plain JavaScript port of Sonner's Toaster shows the toasts with Sonner's own stylesheet, with no npm install and no build step.

  • toast() helper and Sonner facade that flash toasts to the session
  • Sonner's stacking, animations, swipe-to-dismiss and themes
  • Toasts from Livewire actions appear in the same response
  • Browser API with toast(), toast.success(), toast.promise(), toast.loading() and toast.dismiss()
  • Toast text always rendered as text, never as HTML
  • Inline style and script carry Laravel's CSP nonce
A Laravel profile settings form with three Sonner toasts stacked in the bottom-right corner: a green Profile saved toast, an Invite sent toast with an Undo button, and a red Payment failed toast.
A Laravel profile settings form with three Sonner toasts stacked in the bottom-right corner: a green Profile saved toast, an Invite sent toast with an Undo button, and a red Payment failed toast.

Install

Requires PHP 8.3+ and Laravel 12 and 13.

composer require amjadiqbal/laravel-sonner

Usage

// In a controller
toast()->success('Profile saved')->description('Your changes are live.');

return back();

// Once, in your layout, before </body>: <x-sonner />

Setup

The first <x-sonner /> on a page prints the styles and the runtime inline (about 11 KB gzipped), so there is nothing to publish or bundle.

  1. 1 composer require amjadiqbal/laravel-sonner
  2. 2 Add <x-sonner /> to your layout, once, just before </body>.

Toasts from PHP

toast() flashes to the session and survives the redirect. Each toast shows once. The Sonner facade does the same if another package already defines toast().

toast('Event has been created');

toast()->success('Profile saved');
toast()->error('Payment failed')->description('Your card was declined.');

toast()->success('Invite sent')
    ->action('View', route('team.index'))
    ->duration(8000)
    ->position('top-center');

The toaster

<x-sonner /> takes Sonner's <Toaster /> props as attributes. Defaults live in config/sonner.php, published with php artisan vendor:publish --tag=sonner-config.

<x-sonner
    position="top-center"
    theme="system"
    rich-colors
    close-button
    :duration="5000"
/>

From JavaScript

The runtime defines window.toast (unless something else already did) and always window.Sonner, with Sonner's API. toast.custom() is React-only and not available.

toast.success('Saved');

const id = toast.loading('Uploading...');
toast.success('Uploaded', { id });

toast.promise(fetch('/api/report'), {
  loading: 'Building your report...',
  success: (response) => 'Report ready',
  error: 'Could not build the report',
});

Livewire and Alpine

Call toast() in a Livewire action and the toast appears when the request finishes. If the action redirects, including with wire:navigate, the toast waits for the next page. From Alpine, dispatch a sonner:toast event. Set 'livewire' => false in config/sonner.php to turn the Livewire delivery off.

<button x-data @click="$dispatch('sonner:toast', { message: 'Copied!', type: 'success' })">Copy</button>

Hire me

Need this built into your app, or something custom?

I wrote Laravel Sonner. I can wire it into your Laravel app, extend it for your case, or build the feature around it. Tell me what you need and you'll get a plan and a quote, free.

Support

Found a bug or want a feature? Open an issue on GitHub. For help adding it to your own project, use the quote form above.

Need something built?

Free quote in 60 seconds