mirror of
https://github.com/dartdavros/chatballs.git
synced 2026-10-05 09:14:58 +03:00
Онбординг из восьми шагов: приветствие, визард с точным путём и превью результата на каждом шаге, тур «Показать где» с подсветкой реального элемента и финальный экран. Точки возврата — ссылка внизу субменю «Настроек» и пилюля в углу рабочей области. Вёрстка по макету design/baseline/Онбординг. Признак «закрыл» и «прошёл» живёт на членстве человека в организации, а не в localStorage: требование — показать визард всем, кто его ещё не закрывал, включая тех, кто работает в установке давно. У каждого он свой, поэтому один администратор не прячет визард команде. Прогресс шагов считается по факту настройки, ручное «Далее» его не подменяет. Заодно все селекты приложения переведены на общее меню: SelectMenu в shared/ui-controls, поверх него FilterDropdown (фильтры списков) и SelectField (поля форм). Нативных <select> не осталось, вместе с ними ушли пять копий скина селекта. Изменения переплетены с онбордингом через общие файлы (словари, e2e-сценарии), поэтому одним коммитом. Устаревший design/design-system удалён: источник истины по интерфейсу — макеты design/baseline/<фича>/*.dc.html. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
739 lines
14 KiB
CSS
739 lines
14 KiB
CSS
.hub-shell {
|
|
position: relative;
|
|
height: 100vh;
|
|
display: flex;
|
|
overflow: hidden;
|
|
background: var(--n-11);
|
|
}
|
|
|
|
/* Страницы вне чата не адаптированы под мобильный — держат десктопную ширину.
|
|
Чат (кадры M1/M2) адаптивен и ограничение снимает. */
|
|
.hub-shell:not(.is-chat-route) {
|
|
min-width: 1024px;
|
|
}
|
|
|
|
/* Сайдбар 220px (дизайн-базлайн v2, решение 1): фон surface2, без верхней панели. */
|
|
.hub-sidebar {
|
|
position: relative;
|
|
width: var(--sidebar-width, 220px);
|
|
height: 100vh;
|
|
display: flex;
|
|
flex: none;
|
|
flex-direction: column;
|
|
background: var(--surface-sidebar);
|
|
border-right: 1px solid var(--n-8);
|
|
}
|
|
|
|
/* Ручка изменения ширины панели (сайдбар, список диалогов): невидимая полоса
|
|
на правом крае, подсвечивается при наведении и во время перетаскивания. */
|
|
.pane-resizer {
|
|
position: absolute;
|
|
top: 0;
|
|
right: -3px;
|
|
bottom: 0;
|
|
width: 6px;
|
|
z-index: 5;
|
|
cursor: col-resize;
|
|
}
|
|
|
|
.pane-resizer::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 2px;
|
|
width: 2px;
|
|
background: var(--primary);
|
|
opacity: 0;
|
|
transition: opacity 0.12s;
|
|
}
|
|
|
|
.pane-resizer:hover::after,
|
|
.is-resizing > .pane-resizer::after {
|
|
opacity: 1;
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.pane-resizer {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
.hub-sidebar-body {
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* Рейка 60px (дизайн-базлайн v2, кадр S2): показывается только на ≤1024px. */
|
|
.hub-rail {
|
|
display: none;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 14px 0 12px;
|
|
height: 100%;
|
|
}
|
|
|
|
.hub-rail .hub-brand-mark {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.hub-rail-button {
|
|
width: 38px;
|
|
height: 38px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: 0;
|
|
border-radius: 9px;
|
|
color: var(--n-4);
|
|
background: transparent;
|
|
}
|
|
|
|
.hub-rail-button:hover {
|
|
background: var(--n-9);
|
|
}
|
|
|
|
.hub-rail-button.is-active {
|
|
color: var(--primary-text);
|
|
background: var(--primary-bg);
|
|
}
|
|
|
|
.hub-rail-spacer {
|
|
flex: 1;
|
|
}
|
|
|
|
.hub-rail-avatar {
|
|
width: 34px;
|
|
height: 34px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: 0;
|
|
border-radius: 50%;
|
|
color: #ffffff;
|
|
background: var(--primary);
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.hub-rail-backdrop {
|
|
display: none;
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 19;
|
|
border: 0;
|
|
background: rgba(0, 0, 0, 0.25);
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.hub-sidebar {
|
|
width: 60px !important;
|
|
}
|
|
|
|
.hub-rail {
|
|
display: flex;
|
|
}
|
|
|
|
.hub-sidebar-body {
|
|
display: none;
|
|
}
|
|
|
|
.hub-sidebar.is-rail-expanded .hub-rail-backdrop {
|
|
display: block;
|
|
}
|
|
|
|
.hub-sidebar.is-rail-expanded .hub-sidebar-body {
|
|
display: flex;
|
|
position: fixed;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 248px;
|
|
z-index: 20;
|
|
background: var(--surface-card);
|
|
border-right: 1px solid var(--n-8);
|
|
box-shadow: 8px 0 24px rgba(0, 0, 0, 0.1);
|
|
}
|
|
}
|
|
|
|
.hub-brand {
|
|
width: 100%;
|
|
height: 56px;
|
|
display: flex;
|
|
align-items: center;
|
|
flex: none;
|
|
gap: 10px;
|
|
padding: 14px 14px 10px;
|
|
}
|
|
|
|
.hub-brand-mark {
|
|
border: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
/* Переключатель организации (A1): имя + шеврон, 32px. */
|
|
.hub-brand-switch {
|
|
flex: 1;
|
|
min-width: 0;
|
|
height: 32px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 6px;
|
|
padding: 0 6px 0 8px;
|
|
border: 0;
|
|
border-radius: 8px;
|
|
background: transparent;
|
|
color: var(--n-1);
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
text-align: left;
|
|
}
|
|
|
|
.hub-brand-switch:hover {
|
|
background: var(--n-9);
|
|
}
|
|
|
|
.hub-brand-switch span {
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.hub-brand-switch svg {
|
|
flex: none;
|
|
color: var(--n-4);
|
|
}
|
|
|
|
/* «Добавить организацию» в переключателе (A1): такая же строка, как у
|
|
организаций, только на месте значка — пунктирная плитка с плюсом, как у
|
|
«пустого» слота. Ничего залитого: строка читается как действие, а не как
|
|
ещё одна организация, и не спорит с отмеченной текущей. */
|
|
.app-dropdown .ant-dropdown-menu-item button.hub-brand-add {
|
|
color: var(--n-3);
|
|
}
|
|
|
|
.app-dropdown .ant-dropdown-menu-item button.hub-brand-add:hover {
|
|
color: var(--primary-text);
|
|
}
|
|
|
|
/* Селектор длиннее общего «button span { display: block }» из menu.css:
|
|
иначе плюс прижимается к левому верхнему углу плитки. */
|
|
.app-dropdown .ant-dropdown-menu-item button .hub-brand-add-icon {
|
|
width: 17px;
|
|
height: 17px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
color: var(--n-4);
|
|
border: 1.5px dashed var(--n-6);
|
|
border-radius: 6px;
|
|
transition: color 0.15s ease, border-color 0.15s ease;
|
|
}
|
|
|
|
.hub-brand-add-icon svg {
|
|
display: block;
|
|
}
|
|
|
|
.app-dropdown .ant-dropdown-menu-item button.hub-brand-add:hover .hub-brand-add-icon {
|
|
color: var(--primary-text);
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
/* Логотип — сам по себе, без подложки: цвет текста темы. */
|
|
.hub-brand-mark {
|
|
width: 28px;
|
|
height: 28px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
color: var(--n-1);
|
|
background: transparent;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.hub-brand-mark svg {
|
|
width: 26px;
|
|
height: 26px;
|
|
}
|
|
|
|
.hub-brand-mark.has-logo {
|
|
overflow: hidden;
|
|
color: inherit;
|
|
background: var(--surface-card);
|
|
border: 1px solid var(--n-7);
|
|
}
|
|
|
|
.hub-brand-mark img {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.profile-link strong {
|
|
display: block;
|
|
overflow: hidden;
|
|
color: var(--n-1);
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
line-height: 1.3;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.profile-link small {
|
|
display: block;
|
|
overflow: hidden;
|
|
color: var(--n-4);
|
|
font-size: 11.5px;
|
|
font-weight: 400;
|
|
line-height: 1.3;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.hub-nav {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
overflow-y: auto;
|
|
padding: 4px 10px 8px;
|
|
}
|
|
|
|
.hub-nav-item {
|
|
position: relative;
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
flex: none;
|
|
gap: 10px;
|
|
height: 36px;
|
|
padding: 0 10px;
|
|
color: var(--n-2);
|
|
background: transparent;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-size: 13.5px;
|
|
font-weight: 500;
|
|
text-align: left;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.profile-link {
|
|
position: relative;
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: var(--n-3);
|
|
background: transparent;
|
|
border: none;
|
|
text-align: left;
|
|
}
|
|
|
|
.hub-nav-item:not(:disabled):hover,
|
|
.profile-link:hover {
|
|
color: var(--n-2);
|
|
background: var(--n-9);
|
|
}
|
|
|
|
.hub-nav-item.is-active,
|
|
.profile-link.is-active {
|
|
color: var(--primary-text);
|
|
background: var(--primary-bg);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.hub-subnav {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
padding: 2px 0 2px 30px;
|
|
}
|
|
|
|
.hub-subnav-item {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 6px 12px;
|
|
border: 0;
|
|
border-radius: 7px;
|
|
color: var(--n-3);
|
|
background: transparent;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
line-height: 1.4;
|
|
text-align: left;
|
|
}
|
|
|
|
.hub-subnav-item:not(:disabled):hover {
|
|
color: var(--n-2);
|
|
background: var(--n-9);
|
|
}
|
|
|
|
.hub-subnav-item.is-active {
|
|
color: var(--primary-text);
|
|
background: var(--primary-bg);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.hub-subnav-item:disabled {
|
|
color: var(--n-5);
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.hub-nav-chevron {
|
|
display: inline-flex;
|
|
margin-left: auto;
|
|
transition: transform 0.15s ease;
|
|
}
|
|
|
|
.hub-nav-section-toggle[aria-expanded="false"] .hub-nav-chevron {
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
.hub-subnav-item b {
|
|
min-width: 20px;
|
|
height: 20px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-left: auto;
|
|
padding: 0 6px;
|
|
color: #ffffff;
|
|
background: var(--warning);
|
|
border-radius: 10px;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* Бейдж очереди у «Чат» (A1): жёлтая плашка 20px. */
|
|
.hub-nav-badge {
|
|
min-width: 20px;
|
|
height: 20px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-left: auto;
|
|
padding: 0 6px;
|
|
color: var(--warning-text);
|
|
background: var(--warning-bg);
|
|
border: 1px solid var(--warning-border);
|
|
border-radius: 10px;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.hub-nav-group {
|
|
padding: 14px 12px 6px;
|
|
color: var(--n-5);
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.06em;
|
|
}
|
|
|
|
.hub-nav-divider {
|
|
flex: none;
|
|
height: 1px;
|
|
margin: 8px 2px 4px;
|
|
background: var(--n-8);
|
|
}
|
|
|
|
/* Дерево «Диалоги» сотрудника (дизайн-базлайн v2 §3): сайдбар = фильтр чата. */
|
|
.chat-scope-tree {
|
|
padding-bottom: 12px;
|
|
}
|
|
|
|
.chat-scope-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 9px;
|
|
height: 34px;
|
|
padding: 0 8px;
|
|
color: var(--n-1);
|
|
font-size: 13.5px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.chat-scope-section {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
height: 30px;
|
|
margin: 6px 0 0 16px;
|
|
padding: 0 10px 0 12px;
|
|
color: var(--n-4);
|
|
font-size: 12.5px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.chat-scope-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 9px;
|
|
height: 32px;
|
|
padding: 0 10px 0 12px;
|
|
border: 0;
|
|
border-radius: 8px;
|
|
color: var(--n-2);
|
|
background: transparent;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
text-align: left;
|
|
}
|
|
|
|
.chat-scope-item.is-top {
|
|
height: 34px;
|
|
margin-left: 16px;
|
|
}
|
|
|
|
.chat-scope-item.is-nested {
|
|
margin-left: 34px;
|
|
}
|
|
|
|
.chat-scope-item:hover {
|
|
background: var(--n-9);
|
|
}
|
|
|
|
.chat-scope-item.is-active {
|
|
color: var(--primary-text);
|
|
background: var(--primary-bg);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.chat-scope-item > span:not(.chat-scope-agent) {
|
|
flex: 1;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.chat-scope-item small {
|
|
color: var(--n-5);
|
|
font-size: 11.5px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.chat-scope-item.is-active small {
|
|
color: var(--primary-text);
|
|
}
|
|
|
|
.chat-scope-dot {
|
|
flex: none;
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: var(--primary);
|
|
}
|
|
|
|
.chat-scope-dot.is-muted {
|
|
background: var(--n-5);
|
|
}
|
|
|
|
.chat-scope-agent {
|
|
flex: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 18px;
|
|
height: 18px;
|
|
border-radius: 5px;
|
|
color: var(--ai);
|
|
background: color-mix(in srgb, var(--ai) 14%, var(--surface-card));
|
|
}
|
|
|
|
.profile-link {
|
|
margin: 0;
|
|
padding: 12px 14px;
|
|
border-top: 1px solid var(--n-8);
|
|
border-radius: 0;
|
|
}
|
|
|
|
.profile-link:hover {
|
|
background: var(--n-9);
|
|
}
|
|
|
|
.profile-link > span:nth-child(2) {
|
|
min-width: 0;
|
|
flex: 1;
|
|
}
|
|
|
|
.profile-avatar {
|
|
position: relative;
|
|
flex: none;
|
|
display: inline-flex;
|
|
}
|
|
|
|
.profile-avatar .avatar {
|
|
width: 34px;
|
|
height: 34px;
|
|
}
|
|
|
|
/* Онлайн-точка: сотрудник в системе. */
|
|
.profile-avatar i {
|
|
position: absolute;
|
|
right: -1px;
|
|
bottom: -1px;
|
|
width: 10px;
|
|
height: 10px;
|
|
border: 2px solid var(--surface-sidebar);
|
|
border-radius: 50%;
|
|
background: var(--success);
|
|
}
|
|
|
|
.profile-more {
|
|
flex: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 28px;
|
|
height: 28px;
|
|
color: var(--n-4);
|
|
border-radius: 7px;
|
|
}
|
|
|
|
.profile-link:hover .profile-more {
|
|
background: var(--n-8);
|
|
}
|
|
|
|
.profile-more {
|
|
position: relative;
|
|
}
|
|
|
|
/* Непрочитанные уведомления — точка на кнопке меню профиля. */
|
|
.profile-unread {
|
|
position: absolute;
|
|
top: 4px;
|
|
right: 4px;
|
|
width: 7px;
|
|
height: 7px;
|
|
background: var(--error);
|
|
border: 1.5px solid var(--surface-sidebar);
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.profile-menu-badge {
|
|
min-width: 18px;
|
|
height: 18px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-left: auto;
|
|
padding: 0 5px;
|
|
color: #ffffff;
|
|
background: var(--error);
|
|
border-radius: 9px;
|
|
font-size: 10.5px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.avatar {
|
|
width: 32px;
|
|
height: 32px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: none;
|
|
overflow: hidden;
|
|
color: #ffffff;
|
|
background: var(--primary);
|
|
border-radius: 50%;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.avatar.has-photo {
|
|
background: var(--n-9);
|
|
}
|
|
|
|
.avatar img {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.hub-main {
|
|
min-width: 0;
|
|
height: 100vh;
|
|
display: flex;
|
|
flex: 1;
|
|
flex-direction: column;
|
|
}
|
|
|
|
|
|
/* Полоса установки демо-данных: пока worker наполняет организацию, человек
|
|
видит причину пустых разделов, а не гадает. */
|
|
.demo-install-banner {
|
|
display: flex;
|
|
flex: none;
|
|
align-items: center;
|
|
gap: 9px;
|
|
padding: 9px 20px;
|
|
border-bottom: 1px solid var(--n-8);
|
|
background: var(--primary-bg);
|
|
color: var(--primary-text);
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.demo-install-banner.is-done {
|
|
background: var(--success-bg);
|
|
color: var(--success-text);
|
|
}
|
|
|
|
.demo-install-banner.is-failed {
|
|
background: var(--error-bg);
|
|
color: var(--error-text);
|
|
}
|
|
|
|
.update-banner a.link {
|
|
flex: none;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.demo-install-banner > svg {
|
|
flex: none;
|
|
}
|
|
|
|
.demo-install-banner > span {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.demo-install-banner button {
|
|
height: 26px;
|
|
padding: 0 11px;
|
|
border: 1px solid currentColor;
|
|
border-radius: 7px;
|
|
background: transparent;
|
|
color: inherit;
|
|
font-family: inherit;
|
|
font-size: 12.5px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.demo-install-banner .demo-install-close {
|
|
display: flex;
|
|
width: 24px;
|
|
height: 24px;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 0;
|
|
border: 0;
|
|
opacity: 0.65;
|
|
}
|
|
|
|
.demo-install-banner .demo-install-close:hover { opacity: 1; }
|
|
|