Project Overview0:00
Those notifications are one of those little details that make a huge difference in user experience. So here's what we are building today. I have a simple profile settings page where I can update my name, change the theme or update my language. And every time the setting is saved, I see instant feedback with these notifications of different types. Notice how they stack nicely and auto dismiss after a few seconds with smooth animations. Let's build this. So here's what I have to begin with. It's the same profile settings page. It works. That is, it saves. Everything is fine, but I see zero feedback. So let's head over to our Livewire component, which is a single file component. I have everything that's working here. Nothing fancy.
Dispatching First Toast0:49
So let's head over to our Livewire component, which is a single file component. I have everything that's working here. Nothing fancy. Let's start by dispatching an event once the name is updated. So I'll say this dispatch toast with a simple message that says display name updated. Now scroll down completely to the bottom. And here at the end, I will add a div, which I will turn into an Alpine component to receive that event. So here I'm just going to set show as false. We don't want to see the notification, but once there's an event, which is the toast event anywhere on the window, I'm just going to set show to true. Here I'll add another div, which I'm going to show only if the show is set to true. So X show equals show. Add a paragraph where I have the message.
I'm just going to set show to true. Here I'll add another div, which I'm going to show only if the show is set to true. So X show equals show. Add a paragraph where I have the message. So here we'll also set the message as blank. On the event, let's also update the message to event detail message. We'll do set timeout later. So here I set the text to that as message. Yeah, pretty simple. Let me refresh the page and update the name. I will see the notification here. Okay, so let's actually make it look like a notification. I'll position it in the top right corner. You can do it wherever you like. So let me add a class fixed top right. Yeah, top five, right five, Z50, refresh, update. This is where it appears. Let me make it look a little more like a notification. I will just copy paste the markup here. Okay, I've added some classes limited to a width, a green background with a green border, with a green text. So this is a success notification.
Extracting Toast Component2:43
I will just copy paste the markup here. Okay, I've added some classes limited to a width, a green background with a green border, with a green text. So this is a success notification. I've added some text styles as well. Let's see, refresh the page, update the name. Now this looks like a nice success notification. Now before we go further and customize the types of notification, let's extract this toast into a component. So I'll just create a component, views, create a directory, components, create a new file, toast.blade.php. I'm just gonna copy this entire div here, cut it here, and paste it into the blade file. And here, let me just replace this with the toast component. Okay, this should work as it is. Let's check, update the name, and it shows display name updated. Exactly. Now let me add different toast types. So along with show and message,
Adding Toast Types3:43
Okay, this should work as it is. Let's check, update the name, and it shows display name updated. Exactly. Now let me add different toast types. So along with show and message, let's also add type here, which is blank. Let's also change the event listener to update the type that is passed. Your type would be event detail type. And let's change the classes to match the type. So here, I'm just gonna cut all of this. And based on the type, let's add the colors. So we bind the class to this. Yeah, so it's green color if the type is success, it's red, it's if it's error, blue if it's info. All right. And yes, it's yellow if it's warning. To see this in action, let me update the livewire component to emit different types of notifications. So scroll back up. And here, let's change the, let's add a type as success. I will dispatch different notifications in theme and language as well. I've added this if the theme
Stacking Notifications4:47
So scroll back up. And here, let's change the, let's add a type as success. I will dispatch different notifications in theme and language as well. I've added this if the theme is light, I want to show a success notification. If it's dark, I show a warning that it's still in beta. And here, I just show an info. And even when the language is updated, I show info. So now this should work. Let me refresh the page, update the name, it's a success type. Auto, it's info type. Light mode, success again. Dark mode is warning. And changing the language gives me info type again. This is all great, but the notifications are replacing each other. They're not stacking on top. For this, let me go to the toast component. And instead of a single notification, let me change this to an array of toasts. Let me change the event listener as well to push the toast notification. So this would be toasts.push. Let me set the message, the type and show is true. We also need
this to an array of toasts. Let me change the event listener as well to push the toast notification. So this would be toasts.push. Let me set the message, the type and show is true. We also need a toast ID to be able to remove it later after the timeout. So let me just add an ID here, which I will set it to the date timestamp and set the ID here to ID. And now we have to add the single notification toast into a loop. So let's use template X for toast and toasts. Yes. And close the template. And all of this has to be updated to toast.show. All these type will be toast.type. And the message will also be toast.message. All right, let's see if this works. Let me refresh, update. And yes, the notifications are stacking on top of each other. We have to just add some gap between them. Scroll up to the top div. Let's turn this into a flex container. Sorry, flex with flex call. And let me add a gap of three. Let's refresh and try again.
Animating and Auto Dismiss6:58
gap between them. Scroll up to the top div. Let's turn this into a flex container. Sorry, flex with flex call. And let me add a gap of three. Let's refresh and try again. Yes, we have the perfect gap and it's stacking. But notice that the latest notification is appearing at the bottom. We would love to see the latest notifications appear on top while the others scroll down. There's a simple hack for this. We'll simply turn flex call into flex call reverse. Okay, let's try again. Update. Yeah. Notice that the latest notifications are now on top. This is great. Let's make it animate because right now it's just appearing. For animations, we could use X transition, the Alpine directive, but we will not be able to control it the way we want. So let's add some CSS animations. I'll go into my CSS file and add some keyframes right here. Okay. I've added two keyframes fade in down, which makes the notification translate to the
want. So let's add some CSS animations. I'll go into my CSS file and add some keyframes right here. Okay. I've added two keyframes fade in down, which makes the notification translate to the translate from top and fade out up will make it translate from bottom while it fades. Let's also add the tailwind theme variables to be able to use the utility classes, animate fade in down and fade in up. Yeah. Fade in down 0.5 seconds. Maybe ease in and similarly fade in out. Yeah. Ease out. Okay. Let's go back here. When we change the toast.show to true, we want it to fade in, right? So let's add that class here. Animate fade in down toast.show and fade out up when this is false. Let's see what we've got. Let me update the name. Change the theme. Perfect. This is fading in smoothly. That's great for now. It's not yet fading back up because we are not hiding the notifications after a few seconds. Let's do that now. So scroll back up. I'll add a set
fading in smoothly. That's great for now. It's not yet fading back up because we are not hiding the notifications after a few seconds. Let's do that now. So scroll back up. I'll add a set time out here. Yep. Exactly like this. Let's first find the notification with the ID. If index is minus, it's not minus one, then we set the show to false. Yeah. And let we let the notification stay for six seconds. Okay. Let's see what we've got. Update the name. Dark auto. Okay. Let's wait for a few seconds and it is getting removed, but it's disappearing. There's no animation. That's because we have this X show here. The moment show is set to false. We're not giving it any time for animation. It just disappears. I'll remove this and let's see what happens now. Refresh update and wait. So you see the animation is actually happening, but it's not getting removed from the array here. So here let's remove
I'll remove this and let's see what happens now. Refresh update and wait. So you see the animation is actually happening, but it's not getting removed from the array here. So here let's remove it from the array, but not immediately. So we will again face the same issue of it disappearing. Let's add a little time out exactly the amount of time it needs to animate that is 500 milliseconds and remove it immediately after that. So I will add a set time out and remove that particular toast after 500 seconds. This should do it. Let me update the name, change the theme, change the language, wait for a second. And yes, the notifications are smoothly fading back out. Now you can go ahead and experiment further. Maybe add an icon for different types of notifications. Also probably add a manual close button for different types of notifications where there is some information and you don't want it to auto dismiss. You might
different types of notifications. Also probably add a manual close button for different types of notifications where there is some information and you don't want it to auto dismiss. You might want the user to dismiss it. So see you in the next one.
