Skip to content

Instantly share code, notes, and snippets.

@whoisthisstud
Last active September 2, 2024 05:11
Show Gist options
  • Select an option

  • Save whoisthisstud/22dc0b6a56241081bdef372588497b87 to your computer and use it in GitHub Desktop.

Select an option

Save whoisthisstud/22dc0b6a56241081bdef372588497b87 to your computer and use it in GitHub Desktop.
AlpineJS Notification
public function myfunction()
{
// ...other code
$route = route('dashboard');
$this->dispatch('notify', type: 'success', title: 'You did it!'); // minimum
$this->dispatch('notify', type: 'success', title: 'You did it!', content: 'This is your reward'); // additional text
$this->dispatch('notify', type: 'success', title: 'You did it!', content: 'This is your reward', route: $route, target: '_blank'); // include a route
// ...remainder of code
}
<html>
<head>
// ...meta
</head>
<body>
<main class="mainContent">
{{ $slot }}
<x-notifications :delay="5000" />
</main>
</body>
</html>
<button x-data
@click="$dispatch('notify', {type: 'success', title: 'View Content Updated', content: 'This is a really long message that could not fit on one line.'})"
>Success Notification</button>
@props([
'delay' => 4000,
'falloff' => 500,
])
<div
x-data="{
notifications: [],
add(e) {
this.notifications.push({
id: e.timeStamp,
type: e.detail.type,
title: e.detail.title,
content: e.detail.content ?? null,
route: e.detail.route ?? null,
btn: e.detail.btn ?? null,
target: e.detail.target ?? '_self'
})
},
remove(notification) {
this.notifications = this.notifications.filter(i => i.id !== notification.id)
},
}"
@notify.window="add($event)"
class="fixed bottom-0 right-0 flex w-full max-w-sm flex-col space-y-4 px-4 pb-4 sm:justify-start"
role="status"
aria-live="polite"
>
<!-- Notification -->
<template x-for="notification in notifications" :key="notification.id">
<div
x-data="{
show: false,
hovered: false,
init() {
this.$nextTick(() => this.show = true);
setTimeout(() => this.transitionOut(), {{ $delay }});
},
transitionOut(force = false) {
if (this.hovered && !force) {
setTimeout(() => this.transitionOut(), {{ $falloff }});
return;
}
this.show = false;
setTimeout(() => this.remove(this.notification), {{ $falloff }});
},
}"
x-show="show"
x-transition.duration.500ms
class="pointer-events-auto relative w-full md:max-w-sm rounded-md border border-gray-100 dark:border-gray-900 bg-white dark:bg-gray-950 py-4 pl-6 pr-4 shadow-lg"
@mouseover="hovered = true"
@mouseleave="hovered = false"
>
<div class="flex items-start">
<!-- Icons -->
<div x-show="notification.type === 'success'" class="shrink-0">
<svg class="size-5 fill-green-600" viewBox="0 0 512 512">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/>
</svg>
<span class="sr-only">Success:</span>
</div>
<div x-show="notification.type === 'info'" class="shrink-0">
<svg class="size-5 fill-slate-400" viewBox="0 0 512 512">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/>
</svg>
<span class="sr-only">Information:</span>
</div>
<div x-show="notification.type === 'warning'" class="shrink-0">
<svg class="size-5 fill-amber-500" viewBox="0 0 512 512">
<path d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480L40 480c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"/>
</svg>
<span class="sr-only">Warning:</span>
</div>
<div x-show="notification.type === 'error'" class="shrink-0">
<svg class="size-5 fill-red-600" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm97.9-320l-17 17-47 47 47 47 17 17L320 353.9l-17-17-47-47-47 47-17 17L158.1 320l17-17 47-47-47-47-17-17L192 158.1l17 17 47 47 47-47 17-17L353.9 192z"/>
</svg>
<span class="sr-only">Error:</span>
</div>
<div x-show="notification.type === 'bug'" class="shrink-0">
<svg class="size-5 fill-red-600" viewBox="0 0 512 512">
<path class="fa-secondary" opacity=".4" d="M160 96l0 3.6c0 15.7 12.7 28.4 28.4 28.4l135.1 0c15.7 0 28.4-12.7 28.4-28.4l0-3.6c0-53-43-96-96-96s-96 43-96 96zm80 144l0 239.2c5.3 .5 10.6 .8 16 .8s10.7-.3 16-.8L272 240c0-8.8-7.2-16-16-16s-16 7.2-16 16z"/>
<path class="fa-primary" d="M86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l64 64c.7 .7 1.4 1.3 2.1 1.9c-6.2 12-10.1 25.3-11.1 39.5L32 256c-17.7 0-32 14.3-32 32s14.3 32 32 32l64 0c0 24.6 5.5 47.8 15.4 68.6c-2.2 1.3-4.2 2.9-6 4.8l-64 64c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l63.1-63.1c24.5 21.8 55.8 36.2 90.3 39.6L240 240c0-8.8 7.2-16 16-16s16 7.2 16 16l0 239.2c34.5-3.4 65.8-17.8 90.3-39.6l63.1 63.1c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-64-64c-1.9-1.9-3.9-3.4-6-4.8c9.9-20.8 15.4-44.1 15.4-68.6l64 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-64.3 0c-1.1-14.1-5-27.5-11.1-39.5c.7-.6 1.4-1.2 2.1-1.9l64-64c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-64 64c-.7 .7-1.3 1.4-1.9 2.1C345.2 164.1 329.1 160 312 160l-112 0c-17.1 0-33.2 4.1-47.5 11.4c-.6-.7-1.2-1.4-1.9-2.1l-64-64z"/>
</svg>
<span class="sr-only">Bug:</span>
</div>
<!-- Text -->
<div class="ml-3 w-0 flex-1">
<p x-text="notification.title" class="text-sm font-medium leading-5 text-gray-900 dark:text-white"></p>
<p x-text="notification.content"
class="text-sm leading-5 text-gray-700 dark:text-gray-400"
:class="{
'font-mono': notification.type === 'bug',
'font-normal': notification.type !== 'bug'
}"></p>
<a x-show="notification.route !== null"
:href="notification.route"
:target="notification.target"
x-text="notification.btn ? notification.btn : 'View Details'"
class="mt-3 text-xs font-medium leading-5 text-gray-600 hover:text-gray-800 dark:text-gray-500 dark:hover:text-gray-300"
>View Details</a>
</div>
<!-- Remove button -->
<div class="ml-4 flex flex-shrink-0">
<button @click="transitionOut(true)" type="button" class="inline-flex text-gray-400 dark:opacity-50 hover:opacity-100 transition-all duration-150 ease-linear">
<svg aria-hidden class="h-5 w-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>
<span class="sr-only">Close notification</span>
</button>
</div>
</div>
</div>
</template>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment