feat: Добавить анимации и улучшения UX/UI в компоненты приложения, включая плавные переходы, эффекты при наведении и анимации для модальных окон. Обновить карточки и таблицы с новыми анимациями для улучшения визуального восприятия и доступности.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m42s

This commit is contained in:
2025-10-02 19:17:25 +07:00
parent cd5e169bc6
commit 8952c4a897
12 changed files with 1267 additions and 143 deletions
+221
View File
@@ -300,3 +300,224 @@
border-color: var(--tblr-border-color);
}
}
/* ===== UX/UI Enhancement Animations ===== */
/* Плавные переходы для всех интерактивных элементов */
.transition-all {
transition: all 0.2s ease;
}
/* Анимация появления карточек */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card.animate-in {
animation: fadeInUp 0.3s ease-out;
}
/* Анимация при добавлении элемента в таблицу */
@keyframes slideInRight {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.table tbody tr.new-item {
animation: slideInRight 0.3s ease-out;
background-color: rgba(32, 107, 196, 0.1);
}
/* Пульсация при обновлении */
@keyframes pulse {
0%, 100% {
box-shadow: 0 0 0 0 rgba(32, 107, 196, 0.4);
}
50% {
box-shadow: 0 0 0 6px rgba(32, 107, 196, 0);
}
}
.badge.updating {
animation: pulse 1.5s infinite;
}
/* Hover эффекты для интерактивных карточек */
.card.interactive {
cursor: pointer;
transition: all 0.2s ease;
}
.card.interactive:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* Ripple effect для кнопок */
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
.btn-ripple {
position: relative;
overflow: hidden;
}
.btn-ripple::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.btn-ripple:active::after {
width: 100px;
height: 100px;
transition: 0s;
animation: ripple 0.6s ease-out;
}
/* Улучшенная анимация skeleton loader */
@keyframes shimmer {
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
}
.placeholder-glow .placeholder {
animation: shimmer 2s infinite linear;
background: linear-gradient(
90deg,
#f8f9fa 0%,
#e9ecef 50%,
#f8f9fa 100%
);
background-size: 1000px 100%;
}
/* Анимация модальных окон */
.modal.fade.show .modal-dialog {
animation: modalSlideIn 0.3s ease-out;
}
@keyframes modalSlideIn {
from {
opacity: 0;
transform: scale(0.95) translateY(-20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
/* Плавный скролл */
html {
scroll-behavior: smooth;
}
/* Улучшенные focus rings для доступности */
*:focus-visible {
outline: 2px solid var(--tblr-primary, #206bc4);
outline-offset: 2px;
border-radius: 3px;
}
button:focus-visible,
.btn:focus-visible {
box-shadow: 0 0 0 3px rgba(32, 107, 196, 0.3);
}
/* Skip link для клавиатурных пользователей */
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: var(--tblr-primary, #206bc4);
color: white;
padding: 8px 16px;
text-decoration: none;
z-index: 10000;
border-radius: 0 0 4px 0;
transition: top 0.2s;
}
.skip-link:focus {
top: 0;
}
/* Hover эффект для строк таблицы с focus */
.table tr:focus-within {
background-color: rgba(32, 107, 196, 0.05);
}
/* Pulse для кнопок загрузки */
.btn.loading {
position: relative;
}
.btn.loading::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
border-radius: inherit;
background: rgba(255, 255, 255, 0.2);
transform: translate(-50%, -50%);
animation: pulse-button 1.5s infinite;
}
@keyframes pulse-button {
0%, 100% {
opacity: 0;
transform: translate(-50%, -50%) scale(1);
}
50% {
opacity: 1;
transform: translate(-50%, -50%) scale(1.05);
}
}
/* Анимация badge появления */
.badge.animate {
animation: badgePop 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
@keyframes badgePop {
0% {
transform: scale(0);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}