Notifications
A notification feed with dismissible items, unread badges, and clear-all action.
Preview
Notifications5
🎉
Welcome!Your account has been created successfully.2 min ago
💬
New commentAlice replied to your post.15 min ago
⭐
New followerBob started following you.1 hour ago
🔔
ReminderYour subscription renews tomorrow.3 hours ago
📦
Update availableng-oat v2.1 is now available.1 day ago
html
<div class="max-w-lg">
<div class="card">
<header class="hstack justify-between">
<div class="hstack gap-2">
<strong>Notifications</strong>
<ng-oat-badge variant="secondary">{{ notifications().length }}</ng-oat-badge>
</div>
<button class="btn ghost small" (click)="clearAll()">Clear all</button>
</header>
<div class="vstack gap-1">
@for (item of notifications(); track item.id) {
<div class="hstack gap-3 items-start p-2">
<span class="text-3">{{ item.icon }}</span>
<div class="vstack gap-1 flex-1">
<strong class="text-small">{{ item.title }}</strong>
<span class="text-small text-light">{{ item.description }}</span>
<small class="text-light">{{ item.time }}</small>
</div>
<button class="btn ghost small" (click)="dismiss(item.id)">✕</button>
</div>
<hr />
} @empty {
<p class="text-center text-light py-4">No notifications</p>
}
</div>
</div>
</div>SFC Source
typescript
import { Component, signal } from '@angular/core';
import { NgOatBadge } from '@letsprogram/ng-oat';
@Component({
selector: 'app-notifications',
imports: [NgOatBadge],
template: `
<div class="max-w-lg">
<div class="card">
<header class="hstack justify-between">
<div class="hstack gap-2">
<strong>Notifications</strong>
<ng-oat-badge variant="secondary">{{ notifications().length }}</ng-oat-badge>
</div>
<button class="btn ghost small" (click)="clearAll()">Clear all</button>
</header>
<div class="vstack gap-1">
@for (item of notifications(); track item.id) {
<div class="hstack gap-3 items-start p-2">
<span class="text-3">{{ item.icon }}</span>
<div class="vstack gap-1 flex-1">
<strong class="text-small">{{ item.title }}</strong>
<span class="text-small text-light">{{ item.description }}</span>
<small class="text-light">{{ item.time }}</small>
</div>
<button class="btn ghost small" (click)="dismiss(item.id)">✕</button>
</div>
<hr />
} @empty {
<p class="text-center text-light py-4">No notifications</p>
}
</div>
</div>
</div>
`,
})
export class NotificationsComponent {
notifications = signal([
{ id: 1, icon: '🎉', title: 'Welcome!', description: 'Account created.', time: '2 min ago' },
{ id: 2, icon: '💬', title: 'New comment', description: 'Alice replied.', time: '15 min ago' },
{ id: 3, icon: '⭐', title: 'New follower', description: 'Bob followed you.', time: '1 hour ago' },
]);
dismiss(id: number) {
this.notifications.update(list => list.filter(n => n.id !== id));
}
clearAll() {
this.notifications.set([]);
}
}