From 5a801456070b3814a525a9bf9da2e8f6aec035d9 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Mon, 26 Jun 2023 20:13:02 +0100 Subject: [PATCH] css: add notification animation simple slide animation, plus a little scale effect when a duplicate notification gets sent to make the notification more obvious. --- tailwind.config.js | 36 +++++++++++++++++++++++++++++++++++- ts/modules/common.ts | 27 +++++++++++++++++++++------ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/tailwind.config.js b/tailwind.config.js index b9825a6..c51ba96 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -23,10 +23,44 @@ module.exports = { opacity: '0' } }, + 'slide-in': { + '0%': { + opacity: '0', + transform: 'translateY(-100%)' + }, + '100%': { + opacity: '1', + transform: 'translateY(0%)' + }, + }, + 'slide-out': { + '0%': { + opacity: '1', + transform: 'translateY(0%)' + }, + '100%': { + opacity: '0', + transform: 'translateY(-100%)' + }, + }, + 'pulse': { + '0%': { + transform: 'scale(1)' + }, + '50%': { + transform: 'scale(1.05)' + }, + '100%': { + transform: 'scale(1)' + } + } }, animation: { 'fade-in': 'fade-in 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)', - 'fade-out': 'fade-out 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)' + 'fade-out': 'fade-out 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)', + 'slide-in': 'slide-in 0.2s cubic-bezier(.08,.52,.01,.98)', + 'slide-out': 'slide-out 0.2s cubic-bezier(.08,.52,.01,.98)', + 'pulse': 'pulse 0.2s cubic-bezier(0.25, 0.45, 0.45, 0.94)' }, colors: { neutral: colors.slate, diff --git a/ts/modules/common.ts b/ts/modules/common.ts index 4687cc8..c7deb0b 100644 --- a/ts/modules/common.ts +++ b/ts/modules/common.ts @@ -113,7 +113,8 @@ export class notificationBox implements NotificationBox { const closeButton = document.createElement('span') as HTMLSpanElement; closeButton.classList.add("button", "~critical", "@low", "ml-4"); closeButton.innerHTML = ``; - closeButton.onclick = () => { this._box.removeChild(noti); }; + closeButton.onclick = () => this._close(noti); + noti.classList.add("animate-slide-in"); noti.appendChild(closeButton); return noti; } @@ -125,11 +126,21 @@ export class notificationBox implements NotificationBox { const closeButton = document.createElement('span') as HTMLSpanElement; closeButton.classList.add("button", "~positive", "@low", "ml-4"); closeButton.innerHTML = ``; - closeButton.onclick = () => { this._box.removeChild(noti); }; + closeButton.onclick = () => this._close(noti); + noti.classList.add("animate-slide-in"); noti.appendChild(closeButton); return noti; } + private _close = (noti: HTMLElement) => { + noti.classList.remove("animate-slide-in"); + noti.classList.add("animate-slide-out"); + noti.addEventListener(window.animationEvent, () => { + this._box.removeChild(noti); + }, false); + } + + connectionError = () => { this.customError("connectionError", window.lang.notif("errorConnection")); } customError = (type: string, message: string) => { @@ -138,11 +149,13 @@ export class notificationBox implements NotificationBox { noti.classList.add("error-" + type); const previousNoti: HTMLElement | undefined = this._box.querySelector("aside.error-" + type); if (this._errorTypes[type] && previousNoti !== undefined && previousNoti != null) { - previousNoti.remove(); + this._box.removeChild(previousNoti); + noti.classList.add("animate-pulse"); + noti.classList.remove("animate-slide-in"); } this._box.appendChild(noti); this._errorTypes[type] = true; - setTimeout(() => { if (this._box.contains(noti)) { this._box.removeChild(noti); this._errorTypes[type] = false; } }, this.timeout*1000); + setTimeout(() => { if (this._box.contains(noti)) { this._close(noti); this._errorTypes[type] = false; } }, this.timeout*1000); } customPositive = (type: string, bold: string, message: string) => { @@ -151,11 +164,13 @@ export class notificationBox implements NotificationBox { noti.classList.add("positive-" + type); const previousNoti: HTMLElement | undefined = this._box.querySelector("aside.positive-" + type); if (this._positiveTypes[type] && previousNoti !== undefined && previousNoti != null) { - previousNoti.remove(); + this._box.removeChild(previousNoti); + noti.classList.add("animate-pulse"); + noti.classList.remove("animate-slide-in"); } this._box.appendChild(noti); this._positiveTypes[type] = true; - setTimeout(() => { if (this._box.contains(noti)) { this._box.removeChild(noti); this._positiveTypes[type] = false; } }, this.timeout*1000); + setTimeout(() => { if (this._box.contains(noti)) { this._close(noti); this._positiveTypes[type] = false; } }, this.timeout*1000); } customSuccess = (type: string, message: string) => this.customPositive(type, window.lang.strings("success") + ":", message)