feat(frontend): add dynamic animations to login and admin panel

This commit is contained in:
Zuev
2026-02-20 00:48:03 +03:00
parent e9c08b4c75
commit 86a29f6419
9 changed files with 228 additions and 37 deletions

View File

@@ -134,6 +134,15 @@ body {
.nav-item:hover {
background: var(--bg-hover);
color: var(--text-primary);
transform: translateX(4px);
}
.nav-item svg {
transition: transform var(--transition);
}
.nav-item:hover svg {
transform: scale(1.1);
}
.nav-item.active {
@@ -199,12 +208,38 @@ body {
}
/* ===== Cards ===== */
@keyframes slideUpCard {
from {
opacity: 0;
transform: translateY(15px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card {
background: var(--bg-card);
border: 1px solid var(--bg-card-border);
border-radius: var(--radius-md);
padding: 1.5rem;
transition: background 0.4s ease, border-color 0.4s ease;
animation: slideUpCard 0.4s ease-out both;
}
/* Staggered cards */
.card:nth-child(1) {
animation-delay: 0.1s;
}
.card:nth-child(2) {
animation-delay: 0.2s;
}
.card:nth-child(3) {
animation-delay: 0.3s;
}
.card h2 {
@@ -298,6 +333,18 @@ body {
box-shadow: 0 4px 16px var(--accent-glow);
}
@keyframes slideDownAlert {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.form-alert {
display: none;
padding: 0.6rem 1rem;
@@ -311,6 +358,7 @@ body {
background: rgba(248, 113, 113, 0.1);
border: 1px solid rgba(248, 113, 113, 0.2);
color: var(--error);
animation: slideDownAlert 0.3s ease-out both;
}
.form-alert.success {
@@ -318,6 +366,7 @@ body {
background: rgba(52, 211, 153, 0.1);
border: 1px solid rgba(52, 211, 153, 0.2);
color: var(--success);
animation: slideDownAlert 0.3s ease-out both;
}
/* ===== Table ===== */
@@ -347,8 +396,45 @@ tbody td {
border-bottom: 1px solid rgba(255, 255, 255, 0.03);
}
@keyframes slideInRow {
from {
opacity: 0;
transform: translateX(-10px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
tbody tr {
transition: background var(--transition);
animation: slideInRow 0.3s ease-out both;
}
tbody tr:nth-child(1) {
animation-delay: 0.05s;
}
tbody tr:nth-child(2) {
animation-delay: 0.1s;
}
tbody tr:nth-child(3) {
animation-delay: 0.15s;
}
tbody tr:nth-child(4) {
animation-delay: 0.2s;
}
tbody tr:nth-child(5) {
animation-delay: 0.25s;
}
tbody tr:nth-child(n+6) {
animation-delay: 0.3s;
}
tbody tr:hover {
@@ -477,11 +563,29 @@ tbody tr:hover {
font-family: inherit;
font-size: 0.8rem;
cursor: pointer;
transition: background var(--transition);
transition: background var(--transition), transform var(--transition);
}
.btn-delete:hover {
background: rgba(248, 113, 113, 0.2);
transform: scale(1.05);
}
/* ===== Ripple Effect ===== */
.ripple {
position: absolute;
border-radius: 50%;
transform: scale(0);
animation: admin-ripple 0.6s linear;
background-color: rgba(255, 255, 255, 0.3);
pointer-events: none;
}
@keyframes admin-ripple {
to {
transform: scale(4);
opacity: 0;
}
}
/* ===== Mobile Menu Toggle ===== */

View File

@@ -16,6 +16,30 @@
const sidebar = document.querySelector('.sidebar');
const sidebarOverlay = document.getElementById('sidebar-overlay');
// Global Ripple Effect
document.addEventListener('click', function (e) {
const btn = e.target.closest('.btn-create, .btn-delete, .btn-logout');
if (!btn) return;
const rect = btn.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const ripple = document.createElement('span');
ripple.classList.add('ripple');
ripple.style.left = `${x}px`;
ripple.style.top = `${y}px`;
if (getComputedStyle(btn).position === 'static') {
btn.style.position = 'relative';
}
btn.style.overflow = 'hidden';
btn.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
});
// Users
const usersTbody = document.getElementById('users-tbody');
const createForm = document.getElementById('create-form');