Skip to content

Instantly share code, notes, and snippets.

@wmandai
Forked from greenspace10/AppServiceProvider.php
Created June 23, 2021 21:21
Show Gist options
  • Save wmandai/091e735b8b62b7fc5daa6c37837db025 to your computer and use it in GitHub Desktop.
Save wmandai/091e735b8b62b7fc5daa6c37837db025 to your computer and use it in GitHub Desktop.
Laravel, Livewire, Alpine JS Toast Notifications
  1. Create a componet notification.blade.php

  2. Add to your layout

    <x-notification />

  3. Add Macro to your AppServiceProvider.php

  4. Call Macro $this->notify('Some Message', 'Yeah Baby!', 'success');

Options:

- $this->notify('You saved something.');  //Default Success Toast NO TITLE
- $this->notify('You saved something.', 'Success!');  //Default Success Toast WITH TITLE

- $this->notify('You have amessage', 'Message', '');  //Message Toast WITH TITLE

- $this->notify('You saved something.', 'Yay You!', 'success');  	//success Toast WITH TITLE
- $this->notify('Oh No', 'There was a problem', 'error');  		//Error Toast WITH TITLE
- $this->notify('You can't do that...', 'Warning...', 'warning'); 	//Warning Toast WITH TITLE
- $this->notify('Here's Something New!', 'New Product', 'info');  	//Info Toast WITH TITLE	
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Component::macro('notify', function ($message, $title = '', $type = 'success') {
$this->dispatchBrowserEvent('notify', ['message' => $message, 'title' => $title, 'type' => $type]);
});
}
<div
x-data="{
messages: [],
remove(message) {
this.messages.splice(this.messages.indexOf(message), 1)
},
}"
@notify.window="let message = $event.detail; messages.push(message); setTimeout(() => { remove(message) }, 2500)"
class="fixed inset-0 z-50 flex flex-col items-end justify-center px-4 py-6 space-y-4 pointer-events-none sm:p-6 sm:justify-start"
>
<template x-for="(message, messageIndex) in messages" :key="messageIndex" hidden>
<div
x-transition:enter="transform ease-out duration-300 transition"
x-transition:enter-start="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
x-transition:enter-end="translate-y-0 opacity-100 sm:translate-x-0"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="w-full max-w-sm bg-white rounded-lg shadow-lg pointer-events-auto"
>
<div
:class="{
'ring-green-500': message.type === 'success',
'ring-red-500': message.type === 'error',
'ring-blue-500': message.type === 'info',
'ring-yellow-500': message.type === 'warning',
}"
class="w-full max-w-sm overflow-hidden bg-white rounded-lg shadow-lg pointer-events-auto ring-2 ring-opacity-50 ring-black"
>
<div class="p-4">
<div class="flex items-start">
<div class="flex-shrink-0">
<svg x-show="message.type === 'success'" class="w-6 h-6 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg x-show="message.type === 'error'" class="w-6 h-6 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg x-show="message.type === 'info'" class="w-6 h-6 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg x-show="message.type === 'warning'" class="w-6 h-6 text-yellow-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.618 5.984A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016zM12 9v2m0 4h.01" />
</svg>
</div>
<div class="ml-3 w-0 flex-1 pt-0.5">
<p x-text="message.title" class="font-medium text-gray-900 text-md"></p>
<p x-text="message.message" class="mt-1 text-sm text-gray-500"></p>
</div>
<div class="flex flex-shrink-0 ml-4">
<button @click="remove(message)" class="inline-flex text-gray-400 transition duration-150 ease-in-out focus:outline-none focus:text-gray-500">
<svg class="w-5 h-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
</div>
</template>
</div>
@ilearnbydoing
Copy link

Class 'App\Providers\Component' not found

@wmandai
Copy link
Author

wmandai commented Sep 16, 2021

In AppServiceProvider.php

use Illuminate\View\Component;

@ilearnbydoing
Copy link

use Illuminate\View\Component; has no macroable trait
it gives error Call to undefined method Illuminate\View\Component::macro()

@abdisa19
Copy link

abdisa19 commented Jun 3, 2022

use Livewire\Component;

In AppServiceProvider.php

use Illuminate\View\Component;

use Livewire\Component;

@Freddyqt
Copy link

Freddyqt commented Nov 2, 2022

Hello friend, thanks for your work, it works very well! But alpine transitions are not applied, do you know what the problem is? I think it should have a x-show class, but it's using for.

@fvanzeijl
Copy link

fvanzeijl commented Apr 13, 2023

@Freddyqt
Sure, you can use x-show for that. But you have to keep the element hidden first, and show it after next tick:

x-data="{show: false}"
x-init="$nextTick(() => show = true)"
x-show="show"
        <div
            x-data="{show: false}"
            x-init="$nextTick(() => show = true)"
            x-show="show"

            x-transition:enter="transform ease-out duration-300 transition"
            x-transition:enter-start="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
            x-transition:enter-end="translate-y-0 opacity-100 sm:translate-x-0"
            x-transition:leave="transition ease-in duration-100"
            x-transition:leave-start="opacity-100"
            x-transition:leave-end="opacity-0"
            class="w-full max-w-sm bg-white rounded-lg shadow-lg pointer-events-auto"
        >...</div>

@P3p3Segura
Copy link

hjjk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment