Corp/backend/static/css/components/chat-detail.css

730 lines
19 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* chat-detail.css
* Чистая архитектура чата в Telegram/WhatsApp стиле
*/
/* ═══════════════════════════════════════════════════════════
БАЗОВАЯ СТРУКТУРА
═══════════════════════════════════════════════════════════ */
/* КРИТИЧНО: Убираем все внешние скроллы */
body:has(.chat-page) {
overflow: hidden !important;
padding-bottom: 0 !important;
}
body:has(.chat-page) main {
overflow: hidden !important;
padding: 0 !important;
margin: 0 !important;
}
/* Скрываем bottom navbar на странице чата */
body:has(.chat-page) .bottom-navbar {
display: none;
}
/* Страница чата на всю высоту экрана */
.chat-page {
display: flex;
flex-direction: column;
height: calc(100vh - var(--navbar-h));
width: 100%;
max-width: 100%;
overflow: hidden;
background: var(--bs-body-bg);
position: relative;
}
@supports(height: 100svh) {
.chat-page {
height: calc(100svh - var(--navbar-h));
}
}
/* Utility class: Hide scroll element during initialization */
.scroll-hidden {
visibility: hidden !important;
}
.chat-header,
.chat-container {
max-width: 1200px;
margin: 0 auto;
width: 100%;
}
.chat-container {
border-radius: var(--bs-border-radius-lg);
border: 1px solid var(--bs-border-color);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
}
/* ═══════════════════════════════════════════════════════════
ШАПКА ЧАТА
═══════════════════════════════════════════════════════════ */
.chat-header {
flex-shrink: 0;
background: var(--bs-body-bg);
padding: var(--space-2) var(--space-3);
position: sticky;
top: 0;
z-index: 1020;
border-bottom: 1px solid var(--bs-border-color);
}
@media (min-width: 768px) {
.chat-header {
padding: var(--space-3) var(--space-4);
border-bottom: none;
}
}
@media (max-width: 767.98px) {
.chat-header {
padding: var(--space-1) var(--space-2);
}
}
.chat-header-content {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
}
.chat-header-title {
display: flex;
align-items: center;
gap: var(--space-2);
flex: 1;
min-width: 0;
}
.chat-header-title h1 {
font-size: 1.25rem;
font-weight: 700;
margin: 0;
color: var(--bs-body-color);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.chat-header-title i {
font-size: 1.5rem;
flex-shrink: 0;
}
.chat-header-actions {
display: flex;
align-items: center;
gap: var(--space-1);
flex-shrink: 0;
}
/* Аватар чата с бейджем */
.chat-avatar-wrapper {
position: relative;
width: 40px;
height: 40px;
flex-shrink: 0;
}
.chat-avatar {
width: 100%;
height: 100%;
border-radius: 10px;
object-fit: cover;
display: block;
border: 1px solid var(--bs-border-color);
}
.chat-type-badge {
position: absolute;
bottom: -2px;
right: -2px;
width: 20px;
height: 20px;
border-radius: 10px; /* Идеальный круг как в Telegram */
background: var(--bs-danger); /* Красный как непрочитанные */
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 600;
line-height: 1;
border: 2px solid var(--bs-body-bg);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15); /* Мягкая тень */
transition: transform 0.2s ease, background-color 0.2s ease;
}
.chat-type-badge:empty {
display: none;
}
.chat-type-badge.badge-primary {
background: var(--bs-primary);
}
.chat-type-badge.badge-muted {
background: var(--bs-secondary);
}
/* Анимация появления как в Telegram */
@keyframes badge-scale-in {
from {
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
.chat-type-badge.new {
animation: badge-scale-in 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
@media (max-width: 767.98px) {
.chat-header {
padding: var(--space-1) var(--space-2);
}
.chat-header-title h1 {
font-size: 1.1rem;
}
.chat-header-title i {
font-size: 1.25rem;
}
.chat-header-actions .btn-sm span {
display: none;
}
}
/* ═══════════════════════════════════════════════════════════
КОНТЕЙНЕР ЧАТА
═══════════════════════════════════════════════════════════ */
.chat-container {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
overflow: hidden;
position: relative;
}
/* ═══════════════════════════════════════════════════════════
EMOJI PICKER
═══════════════════════════════════════════════════════════ */
.chat-emoji-picker {
position: absolute;
bottom: 100%;
right: 0;
margin-bottom: var(--space-2);
z-index: 1050;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
border-radius: var(--bs-border-radius-lg);
max-width: 90vw;
}
@media (min-width: 768px) {
.chat-emoji-picker {
right: var(--space-3);
}
}
/* Скрываем по умолчанию, показываем через JS */
.chat-emoji-picker:not([data-visible="true"]) {
display: none;
}
/* ═══════════════════════════════════════════════════════════
ОБЛАСТЬ СООБЩЕНИЙ
═══════════════════════════════════════════════════════════ */
.chat-messages-scroll {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: var(--space-3);
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
scrollbar-color: color-mix(in srgb, var(--bs-body-color), transparent 70%) transparent;
/* CSS Containment для оптимизации (как в Telegram) */
contain: layout style paint;
will-change: scroll-position;
/* GPU acceleration для плавного scroll */
transform: translateZ(0);
backface-visibility: hidden;
perspective: 1000px;
}
.chat-messages-scroll:hover {
scrollbar-color: color-mix(in srgb, var(--bs-body-color), transparent 55%) transparent;
}
.chat-messages-scroll::-webkit-scrollbar {
width: 8px;
}
.chat-messages-scroll::-webkit-scrollbar-track {
background: transparent;
}
.chat-messages-scroll::-webkit-scrollbar-thumb {
background-color: color-mix(in srgb, var(--bs-body-color), transparent 75%);
border-radius: 4px;
}
.chat-messages-scroll:hover::-webkit-scrollbar-thumb {
background-color: color-mix(in srgb, var(--bs-body-color), transparent 55%);
}
@media (hover: none), (pointer: coarse) {
.chat-messages-scroll {
scrollbar-width: none;
}
.chat-messages-scroll::-webkit-scrollbar {
display: none;
}
}
@media (max-width: 767.98px) {
.chat-messages-scroll {
padding: var(--space-2);
}
}
/* ═══════════════════════════════════════════════════════════
ИНДИКАТОР ПЕЧАТИ
═══════════════════════════════════════════════════════════ */
.chat-typing-indicator {
flex-shrink: 0;
padding: var(--space-1) var(--space-3);
font-size: 0.875rem;
color: var(--bs-secondary);
min-height: 32px;
display: flex;
align-items: center;
gap: var(--space-1);
}
.chat-typing-indicator.d-none {
display: none !important;
}
/* ═══════════════════════════════════════════════════════════
КОМПОЗЕР (ФОРМА ВВОДА)
═══════════════════════════════════════════════════════════ */
.chat-composer-wrapper {
flex-shrink: 0;
padding: var(--space-3) var(--space-3);
padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
background: var(--bs-body-bg);
border-top: 1px solid var(--bs-border-color);
position: relative;
z-index: 1010;
}
@media (min-width: 768px) {
.chat-composer-wrapper {
padding: var(--space-3) var(--space-4);
padding-bottom: var(--space-3);
border-radius: 0 0 var(--bs-border-radius-lg) var(--bs-border-radius-lg);
}
}
@media (max-width: 767.98px) {
.chat-composer-wrapper {
padding: var(--space-2) var(--space-2);
.message-field {
display: flex;
align-items: flex-end;
gap: var(--space-1);
width: 100%;
}
.composer-input-group {
flex: 1;
display: flex;
align-items: flex-end;
gap: var(--space-1);
background: var(--bs-tertiary-bg);
border-radius: var(--bs-border-radius-lg);
padding: var(--space-1);
border: 1px solid color-mix(in srgb, var(--bs-border-color), transparent 50%);
transition: border-color 0.2s;
}
.composer-input-group:focus-within {
border-color: var(--bs-primary);
}
.message-input {
flex: 1;
resize: none;
border: none;
background: transparent;
outline: none;
font-size: 1rem;
line-height: 1.5;
padding: var(--space-1);
max-height: 120px;
overflow-y: auto;
scrollbar-width: thin;
color: var(--bs-body-color);
}
.message-input::placeholder {
color: var(--bs-secondary-color);
}
.message-input::-webkit-scrollbar {
width: 4px;
}
.message-input::-webkit-scrollbar-thumb {
background-color: color-mix(in srgb, var(--bs-body-color), transparent 70%);
border-radius: 2px;
}
.composer-actions {
display: flex;
gap: 2px;
align-items: center;
}
.btn-send {
background: var(--bs-primary);
color: white;
border: none;
border-radius: 50%;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
flex-shrink: 0;
padding: 0;
}
.btn-send:hover:not(:disabled) {
background: color-mix(in srgb, var(--bs-primary), black 10%);
transform: scale(1.05);
color: white;
}
.btn-send:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-attachment,
.message-icon-btn {
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
color: var(--bs-body-color);
background: transparent;
border: none;
padding: 0;
}
.btn-attachment:hover,
.message-icon-btn:hover {
background: color-mix(in srgb, var(--bs-body-color), transparent 90%);
}
/* ═══════════════════════════════════════════════════════════
СООБЩЕНИЯ (BUBBLES)
═══════════════════════════════════════════════════════════ */
.bubble {
border-radius: 16px;
padding: var(--space-1) var(--space-2);
word-break: break-word;
white-space: pre-wrap;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
max-width: 75%;
}
@media (max-width: 767.98px) {
.bubble {
max-width: 85%;
}
}
.bubble-me {
background: color-mix(in srgb, var(--bs-primary) 92%, #fff 0%);
color: #fff;
}
.bubble-other {
background: var(--bs-secondary-bg);
color: var(--bs-body-color);
}
.mini-ava {
width: 32px;
height: 32px;
border-radius: 9999px;
overflow: hidden;
display: grid;
place-items: center;
background: var(--bs-secondary-bg);
flex-shrink: 0;
}
.mini-ava img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
/* ═══════════════════════════════════════════════════════════
ВЛОЖЕНИЯ
═══════════════════════════════════════════════════════════ */
.message-attachments {
margin-top: var(--space-1);
}
.attachment-preview {
padding: var(--space-1) 0;
max-height: 200px;
overflow-y: auto;
}
.attachment-item {
background: var(--bs-secondary-bg);
border-radius: var(--bs-border-radius);
padding: var(--space-1);
transition: background-color 0.15s;
}
.attachment-item:hover {
background: var(--bs-tertiary-bg);
}
.chat-media {
max-width: 100%;
max-height: 400px;
border-radius: 12px;
}
/* ═══════════════════════════════════════════════════════════
РАЗДЕЛИТЕЛИ
═══════════════════════════════════════════════════════════ */
.day-divider,
.unread-divider {
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-1);
margin: var(--space-1) 0 var(--space-2);
font-size: .85rem;
line-height: 1;
font-weight: 700;
pointer-events: none;
user-select: none;
}
.day-divider::before,
.day-divider::after,
.unread-divider::before,
.unread-divider::after {
content: "";
flex: 1 1 auto;
height: 1px;
background: color-mix(in srgb, var(--bs-border-color), transparent 30%);
}
.day-divider > span,
.unread-divider > span {
flex: 0 0 auto;
padding: 0 var(--space-1);
background: transparent;
}
.day-divider {
color: var(--bs-secondary-color);
}
.unread-divider {
color: var(--bs-danger);
}
/* ═══════════════════════════════════════════════════════════
КНОПКА "ВНИЗ"
═══════════════════════════════════════════════════════════ */
.scroll-to-bottom {
position: absolute;
right: var(--space-2);
bottom: calc(80px + var(--space-2));
z-index: 2;
display: none;
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--bs-primary);
color: white;
border: none;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
transition: all 0.2s;
}
@media (max-width: 767.98px) {
.scroll-to-bottom {
bottom: calc(var(--space-5) + 80px + env(safe-area-inset-bottom, 12px));
}
}
.scroll-to-bottom.show {
display: flex;
align-items: center;
justify-content: center;
}
.scroll-to-bottom:hover {
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
/* ═══════════════════════════════════════════════════════════
BADGE НЕПРОЧИТАННЫХ НА SCROLL BTN
Унифицирован со стилем sticky-date
═══════════════════════════════════════════════════════════ */
.scroll-to-bottom {
position: relative !important; /* Для абсолютного позиционирования badge */
}
.scroll-to-bottom .unread-badge {
position: absolute;
top: -8px;
right: -8px;
z-index: 1;
/* Layout - как у sticky-date span */
display: flex !important; /* По умолчанию flex для правильного позиционирования */
align-items: center;
justify-content: center;
min-width: 20px;
height: 20px;
padding: 0 6px;
/* Typography - как у sticky-date */
font-size: 11px !important;
font-weight: 600 !important;
line-height: 1 !important;
color: white !important;
/* Visual - унифицировано с sticky-date */
background-color: var(--bs-danger) !important;
border-radius: 10px !important;
border: 2px solid var(--bs-body-bg) !important; /* Контраст с фоном */
/* Shadow - как у sticky-date */
box-shadow: 0 2px 6px rgba(220, 53, 69, 0.4) !important;
/* Transitions - как у sticky-date */
transition: background-color 0.2s ease, box-shadow 0.2s ease, transform 0.15s ease !important;
/* Анимация появления */
animation: badgePulse 0.3s ease;
}
/* Класс для скрытия badge */
.scroll-to-bottom .unread-badge.badge-hidden {
display: none !important;
}
/* Кнопка с непрочитанными - subtle pulse как у sticky-date.interactive */
.scroll-to-bottom.has-unread {
animation: buttonPulse 2s ease infinite !important;
}
/* Анимации */
@keyframes badgePulse {
0% {
transform: scale(0);
opacity: 0;
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
opacity: 1;
}
}
@keyframes buttonPulse {
0%, 100% {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
50% {
box-shadow: 0 4px 16px rgba(var(--bs-primary-rgb), 0.4);
}
}
/* ═══════════════════════════════════════════════════════════
ИНДИКАТОР ЗАГРУЗКИ
═══════════════════════════════════════════════════════════ */
.history-loader {
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-1);
padding: var(--space-2) 0;
color: var(--bs-secondary);
}
.history-loader .spinner-border {
width: 1rem;
height: 1rem;
}
/* ═══════════════════════════════════════════════════════════
ТЕМНАЯ ТЕМА
═══════════════════════════════════════════════════════════ */
[data-bs-theme="dark"] .chat-messages-scroll {
scrollbar-color: color-mix(in srgb, var(--bs-body-color), transparent 78%) transparent;
}
[data-bs-theme="dark"] .chat-messages-scroll:hover {
scrollbar-color: color-mix(in srgb, var(--bs-body-color), transparent 60%) transparent;
}
[data-bs-theme="dark"] .chat-type-badge {
border-color: var(--bs-body-bg);
}