Skip to content

Commit

Permalink
feat: Implement Stacked Notifications with Auto and Manual Dismissal
Browse files Browse the repository at this point in the history
- Added StackedNotificationManager class to handle creation, management, and dismissal of stacked notifications.
- Notifications are displayed in a stack format with the newest at the top.
- Added automatic dismissal feature with customizable timeouts.
- Added manual dismissal option via a close button.
- Included functionality to clear all active notifications at once.
  • Loading branch information
caioalvesbraga committed Aug 15, 2024
1 parent 12a7a6d commit 184f4c7
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 0 deletions.
50 changes: 50 additions & 0 deletions js/src/stackedNotification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export class StackedNotificationManager {
constructor() {
this.notifications = [];
this.container = this._createStackedNotificationContainer();
}

_createStackedNotificationContainer() {
const container = document.createElement('div');
container.className = 'stacked-notification-container';
document.body.appendChild(container);
return container;
}

createStackedNotification(type, message, autoDismiss = true, dismissTime = 3000) {
const notification = document.createElement('div');
notification.className = `stacked-notification stacked-notification-${type}`;
notification.innerText = message;

const closeBtn = document.createElement('button');
closeBtn.className = 'close-btn';
closeBtn.innerHTML = '×';
closeBtn.onclick = () => this.removeStackedNotification(notification);

notification.appendChild(closeBtn);
this.container.appendChild(notification);

this.notifications.push(notification);

if (autoDismiss) {
setTimeout(() => {
if (notification.parentNode) {
this.removeStackedNotification(notification);
}
}, dismissTime);
}
}


removeStackedNotification(notification) {
if (notification && notification.parentNode === this.container) {
this.container.removeChild(notification);
this.notifications = this.notifications.filter(n => n !== notification);
}
}


clearAllStackedNotifications() {
this.notifications.forEach(notification => this.removeStackedNotification(notification));
}
}
38 changes: 38 additions & 0 deletions js/tests/unit/stackedNotification.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { StackedNotificationManager } from '../../src/stackedNotification';

describe('StackedNotificationManager', () => {
let stackedNotificationManager;

beforeEach(() => {
stackedNotificationManager = new StackedNotificationManager();
});

afterEach(() => {
stackedNotificationManager.clearAllStackedNotifications();
});

it('should create a stacked notification and add it to the DOM', () => {
stackedNotificationManager.createStackedNotification('success', 'Success message');
const notifications = document.querySelectorAll('.stacked-notification');
expect(notifications.length).toBe(1);
expect(notifications[0].classList.contains('stacked-notification-success')).toBe(true);
expect(notifications[0].innerText.includes('Success message')).toBe(true);
});

it('should automatically remove the stacked notification after a certain time', (done) => {
stackedNotificationManager.createStackedNotification('error', 'Error message', true, 1000);
setTimeout(() => {
const notifications = document.querySelectorAll('.stacked-notification');
expect(notifications.length).toBe(0);
done();
}, 1500);
});

it('should allow manual removal of stacked notifications', () => {
stackedNotificationManager.createStackedNotification('warning', 'Warning message');
const notification = document.querySelector('.stacked-notification');
notification.querySelector('.close-btn').click();
const notifications = document.querySelectorAll('.stacked-notification');
expect(notifications.length).toBe(0);
});
});
41 changes: 41 additions & 0 deletions scss/_stackedNotification.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.stacked-notification-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
max-width: 300px;
}

.stacked-notification {
background-color: #f0f0f0;
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
display: flex;
justify-content: space-between;
align-items: center;

&.stacked-notification-success {
border-color: #28a745;
background-color: #d4edda;
}

&.stacked-notification-error {
border-color: #dc3545;
background-color: #f8d7da;
}

&.stacked-notification-warning {
border-color: #ffc107;
background-color: #fff3cd;
}
}

.close-btn {
background: none;
border: none;
font-size: 16px;
cursor: pointer;
color: #000;
}

0 comments on commit 184f4c7

Please sign in to comment.