Hey guys, how are you!?
Today we are going to learn and build a cool animated notifications menu, using Angular standalone components, Angular animations and Bootstrap!
Below you can see our final project and you will be able to reuse the animation and make other animations even more beautiful!
✵ Project Informations
Here you can find the project informations and the Angular CLI
I used to generate the project:
// Project generate with
private readonly generatedInformation = 'Angular CLI 15.2.0';
// Dependencies
const projectInformations: Informations[] = [
{
tecnologie: 'Angular',
version: '15.2.0',
},
{
tecnologie: 'Angular Animations',
version: '15.2.0',
},
{
tecnologie: 'Bootstrap',
version: '5.2.3',
},
];
✵ Creating the project
In your preferred folder, create a new Angular project with router-outlet and with scss:
ng new angular-menu-notifications
---
? Would you like to add Angular routing? Yes
---
? Which stylesheet format would you like to use? SCSS
After that open it in your preferred Code Editor.
✵ Installing Bootstrap and Importing
First, let's install the Bootstrap dependency:
npm i bootstrap
Now, let's import the Bootstrap styles, in your styles.scss file import it:
@import "bootstrap/scss/bootstrap";
For the scripts, in the scripts array in your angular.json
file import the bootstrap.bundle.min.js, like below:
"scripts": [
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
],
Niice, now we have the Bootstrap already for us and we can use it!
Let's implement the structure 😋😋
✵ Styling the project:
➝ Importing the Google Fonts:
In your index.html
inside of the head
tag let's import the
Google Poppins font API:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;600&display=swap" rel="stylesheet"/>
➝ Styling the global style's project:
Now, let's change some bootstrap classes styles, so in our styles.scss
let's insert the code below:
/* You can add global styles to this file, and also import other style files */
@import "bootstrap/scss/bootstrap";
$primary: #1e1e1e;
$secondary: #181818;
$warning: #C5F7C9;
.bg-primary {
background-color: $primary !important;
}
.bg-secondary {
background-color: $secondary !important;
}
.text-warning {
color: $warning !important;
}
.border-warning {
border-color: $warning !important;
}
.offcanvas {
width: 450px !important;
padding: 0 1rem;
}
.text-bg-warning {
background-color: $warning !important;
}
body {
min-height: 100vh;
background-color: $primary;
}
I don't really like to insert styling code in this file, I prefer to create a
resources
folder and isolate it in some folders/files with style properties! I prefer to do this so that the project is more organized and easier to maintain. But this example is a small project, so let's do it like the example!
✵ Creating the Notification Model
Our notification will have three properties, title, createdAt, description, so let's generate the model and insert the properties:
ng g i models/notifications
And the code will be like below:
export interface Notification {
title: string;
createdAt: string;
description: string;
}
✵ Creating and Implementing the Header:
Let's generate our standalone header component in a components folder, so to generate we write:
ng g c components/header --standalone
Now, for our header structure we'll use the bootstrap navbar and we need a button with bootstrap offcanvas properties, so the code will be like below:
<header>
<nav class="navbar navbar-dark bg-secondary">
<div class="container-fluid">
<button class="ms-auto navbar-toggler"
type="button"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasNotifications"
aria-controls="offcanvasNotifications">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>
</header>
Now we need to import it in your app.module.ts
and insert in the app.component.html
:
➝ App Module:
@NgModule({
...
imports: [
...
HeaderComponent,
],
...
})
➝ App Html:
<app-header></app-header>
<router-outlet></router-outlet>
And now our project will be like below, with the header and styles configuration:
✵ Creating the Card component
Now we will create our card-notification
standalone component using the bootstrap card component!
➝ Generating the component:
ng g c components/card-notification --standalone
We will have three properties, title, createdAt and description as our Notification
interface! And the card-notification
will receive the notification with the @Input()
bind, our card-notification
code will be as below:
➝ Notification Card HTML:
<div class="bg-primary border-warning card">
<div class="card-body">
<h3 class="text-warning fw-bold card-title">
{{ notification.title }}
</h3>
<span class="badge text-bg-warning card-date">
{{ notification.createdAt }}
</span>
<p class="card-text">
{{ notification.description }}
</p>
</div>
</div>
➝ Notification Card Class:
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Notification } from '../../models/notification';
...
export class CardNotificationComponent {
@Input() notification: Notification;
}
➝ Notification Card Style:
.card {
border-radius: 25px;
margin-bottom: 1.5rem;
border-width: 2px;
border-style: solid;
color: white;
&-title {
font-size: 1rem;
font-family: 'Poppins', sans-serif;
font-weight: 500;
}
&-date {
font-size: 0.75rem;
margin-bottom: 0.75rem;
border-radius: 5px;
}
&-text {
font-size: 0.825rem;
font-family: 'Poppins', sans-serif;
font-weight: 300;
}
}
Annd done, now we'd our card-notification
component 🥳🥳🥳
✵ Creating the menu
We'll use bootstrap offcanvas to make our menu, so let's generate the menu-notifications
component and its structure:
➝ Generating the component:
ng g c components/menu-notifications --standalone
Now, let's insert the bootstrap offcanvas structure, insert the card-notification
component inside the offcanvas-body
and inside it we'll make an ng-container
with *ngFor
to display some dummy notifications created in our menu-notification.component.ts
, and it will be like:
➝ Menu Notification HTML:
<div class="offcanvas offcanvas-end bg-secondary"
data-bs-backdrop="static"
tabindex="-1"
id="offcanvasNotifications"
aria-labelledby="offcanvasNotificationsLabel">
<div class="offcanvas-header">
<h2 class="h5 text-white offcanvas-title"
id="offcanvasNotificationsLabel">
All Notifications
</h2>
<button type="button"
class="btn-close"
data-bs-dismiss="offcanvas"
aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<ng-container *ngFor="let notification of notificationsMockup">
<app-card-notification [notification]="notification"></app-card-notification>
</ng-container>
</div>
</div>
➝ Menu Notification CLASS:
...
import { Notification } from '../../models/notification';
import {
CardNotificationComponent
} from '../card-notification/card-notification.component';
@Component({
...
imports: [
CommonModule,
CardNotificationComponent
],
...
})
export class MenuNotificationsComponent {
notificationsMockup: Notification[] = [
{
title: 'What is Lorem Ipsum?',
createdAt: '2023-02-21',
description:
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
},
{
title: 'What is Lorem Ipsum?',
createdAt: '2023-02-21',
description:
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
},
{
title: 'What is Lorem Ipsum?',
createdAt: '2023-02-21',
description:
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
},
{
title: 'What is Lorem Ipsum?',
createdAt: '2023-02-21',
description:
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
},
];
}
And here we can see how our project are, take a look:
✵ Implementing the Angular Animation
Now let's implement Angular Animation
and make our menu notifications
cooler!
First, when we use Angular Animation
we need to import the BrowserAnimationsModule
, so let's import it into our app.module.ts
...
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
...
imports: [
...
BrowserAnimationsModule,
...
],
...
})
export class AppModule { }
➝ Creating the Animation:
First let's create an animations
folder in our app
folder and inside it we'll create an animations.ts.
file, so the structure of the folder will look like this:
| src
| ---animations
| -----animations.ts
|
Now our cards will have a transitionY
, opacity
and offset
changes, so our animations.ts
using Angular Animations will look like below:
import { animate, keyframes, query, stagger, state, style, transition, trigger } from '@angular/animations';
export const animateListItems =
trigger('listAnimation', [
transition('* => *', [
query(':enter', style({
opacity: 0,
}), {optional: true}),
query(':enter', stagger('300ms', [
animate('1.3s ease-in', keyframes([
style({opacity: 0, transform: 'translateY(380px)', offset: 0}),
style({opacity: .5, transform: 'translateY(-8px)', offset: 0.5}),
style({opacity: 1, transform: 'translateY(0)', offset: 1}),
]))
]), {optional: true})
])
]);
Now, let's add some new structures to our menu-notifications.component.html
and import the animation.ts
inside the animations
array in menu-notifications.component.ts
:
➝ Menu Notifications HTML:
<div class="offcanvas offcanvas-end bg-secondary"
data-bs-backdrop="static"
tabindex="-1"
id="offcanvasNotifications"
aria-labelledby="offcanvasNotificationsLabel">
...
<div class="offcanvas-body">
<ng-container *ngIf="showNotificationsContainer">
<div [@listAnimation]="notificationsMockup.length">
<div *ngFor="let notification of notificationsMockup">
<app-card-notification [notification]="notification"></app-card-notification>
</div>
</div>
</ng-container>
</div>
</div>
➝ Menu Notifications CLASS:
import { animateListItems } from '../../animations/animations';
@Component({
...
animations: [
animateListItems
]
})
And lastly, we need to apply the animation when the [shown.bs.offcanvas](https://getbootstrap.com/docs/5.2/components/offcanvas/#events)
events occur in our #offcanvasNotifications
, so inside the menu-notifications.component.ts
we will insert the method below:
export class MenuNotificationsComponent implements OnInit {
showNotificationsContainer = false;
...
ngOnInit(): void {
this.listEndAnimationenOpenOffCanvas();
}
listEndAnimationenOpenOffCanvas(): void {
const notificationsOffcanvas = document.getElementById('offcanvasNotifications');
if (!notificationsOffcanvas){
return;
}
notificationsOffcanvas.addEventListener('shown.bs.offcanvas', () => {
console.log('entrou');
this.showNotificationsContainer = true;
});
}
}
And finally, we have our animation in the Notifications Menu
working like a charm 🥳🥹😋🥳🥹😋
Below you can see the animation working:
Now we have our notifications menu animated using Angular animations and fully reusable!
And we can use our imagination now to enhance and create other wonderful animations!
If you liked the project, please give a star in the repository: Github Repository.
And you can forked it, too!
I hope you enjoyed it and that this article helps you!
See you later guys 🖖🖖🖖