fix(room): адаптивный тулбар — плавное сжатие кнопок вместо оверфлоу
Задачи B1/B2 добавили в тулбар «Рука» и «Очередь» (до 11 кнопок вместо исходных 8) — на промежуточных ширинах (~600–1100px) кнопки вылезали за края тулбара: жёсткого мобильного брейкпоинта (≤600px, скрывает три кнопки) не хватало, а до него сжатия не было вовсе. Иконка/отступы/зазоры/шрифт кнопок теперь плавно уменьшаются на диапазоне 1200px → 600px через `clamp()` с явной линейной интерполяцией (обычный `clamp(min, Nvw, max)` не подошёл — подобранный N упирался в потолок уже на довольно широких экранах, сжатие получалось резким скачком заметно раньше нужной ширины, а не плавным). Нижние границы совпадают с тем, что жёстко выставляет мобильный медиа-запрос на 600px — переход в него визуально бесшовный. Побочный эффект сжатия: подпись «Мини-окно» на промежуточных ширинах переносилась на 2 строки и делала эту кнопку выше соседних. Ниже 1200px показываем короткое «Мини» вместо полной подписи — кнопка остаётся однострочной; aria-label по-прежнему несёт полный смысл для скринридеров.
This commit is contained in:
@@ -247,7 +247,14 @@ export function RoomToolbar({
|
|||||||
<span className="icon-shell">
|
<span className="icon-shell">
|
||||||
<PictureInPicture2 className="lucide" aria-hidden="true" />
|
<PictureInPicture2 className="lucide" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
<span className="label">Мини-окно</span>
|
{/* На узком экране («Мини-окно» иначе переносится на 2 строки и
|
||||||
|
кнопка становится выше соседних, см. .label-full/.label-short
|
||||||
|
в room.css) — только «Мини». Текст, не структура: aria-label
|
||||||
|
выше уже несёт полный смысл независимо от видимой подписи. */}
|
||||||
|
<span className="label">
|
||||||
|
<span className="label-full">Мини-окно</span>
|
||||||
|
<span className="label-short">Мини</span>
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -277,32 +277,54 @@ video[data-lk-source='screen_share'] { object-fit: contain; background: #000; }
|
|||||||
.stage-show-others svg { width: 18px; height: 18px; flex-shrink: 0; }
|
.stage-show-others svg { width: 18px; height: 18px; flex-shrink: 0; }
|
||||||
|
|
||||||
/* Нижний тулбар: свои кнопки на хуках LiveKit (TrackToggle/DisconnectButton) */
|
/* Нижний тулбар: свои кнопки на хуках LiveKit (TrackToggle/DisconnectButton) */
|
||||||
|
/*
|
||||||
|
* Кнопки тулбара плавно уменьшаются (иконка/отступы/шрифт/зазор) на всём
|
||||||
|
* диапазоне 1200px → 600px — до этого тулбар стал шире, чем при исходном
|
||||||
|
* проектировании (задачи B1/B2 добавили «Рука»/«Очередь», раньше помещались
|
||||||
|
* без сжатия 8 кнопок, теперь до 11 — без этого блока получался
|
||||||
|
* горизонтальный оверфлоу вплоть до самого мобильного брейкпоинта, кнопки
|
||||||
|
* вылезали за края тулбара).
|
||||||
|
*
|
||||||
|
* Обычный `clamp(min, Nvw, max)` тут не подходит: подобранный `N`
|
||||||
|
* дотягивается до `max` уже на довольно узких экранах (например,
|
||||||
|
* `3vw` = 24px ровно на 800px viewport) и дальше просто стоит на потолке —
|
||||||
|
* получается не плавное сжатие в нужном диапазоне, а резкий скачок сильно
|
||||||
|
* раньше нужной ширины (поймали именно так на первой версии этого блока).
|
||||||
|
* Вместо этого — явная линейная интерполяция между двумя точками
|
||||||
|
* (600px→минимум, 1200px→максимум): `calc(MIN + (MAX-MIN) * (100vw - 600px)
|
||||||
|
* / 600)`, снаружи в `clamp()` только чтобы намертво остановиться на
|
||||||
|
* границах диапазона. Нижние границы — те же значения, что жёстко
|
||||||
|
* выставляет мобильный медиа-запрос ниже (`max-width: 600px`), поэтому
|
||||||
|
* переход в него на 600px визуально бесшовный.
|
||||||
|
*/
|
||||||
.room-toolbar {
|
.room-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: var(--space-2);
|
gap: clamp(2px, calc(2px + (100vw - 600px) * 6 / 600), var(--space-2));
|
||||||
background: var(--color-room-surface);
|
background: var(--color-room-surface);
|
||||||
border-top: 1px solid var(--color-room-tile-border);
|
border-top: 1px solid var(--color-room-tile-border);
|
||||||
padding: var(--space-3) var(--space-6);
|
padding: var(--space-3) clamp(8px, calc(8px + (100vw - 600px) * 16 / 600), var(--space-6));
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.tb-btn {
|
.tb-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: clamp(2px, calc(2px + (100vw - 600px) * 2 / 600), 4px);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 8px 18px;
|
padding:
|
||||||
|
clamp(6px, calc(6px + (100vw - 600px) * 2 / 600), 8px)
|
||||||
|
clamp(6px, calc(6px + (100vw - 600px) * 12 / 600), 18px);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
color: var(--color-room-text-primary);
|
color: var(--color-room-text-primary);
|
||||||
min-width: 76px;
|
min-width: clamp(0px, calc((100vw - 600px) * 76 / 600), 76px);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.tb-btn .icon-shell {
|
.tb-btn .icon-shell {
|
||||||
width: 48px;
|
width: clamp(40px, calc(40px + (100vw - 600px) * 8 / 600), 48px);
|
||||||
height: 48px;
|
height: clamp(40px, calc(40px + (100vw - 600px) * 8 / 600), 48px);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -311,9 +333,27 @@ video[data-lk-source='screen_share'] { object-fit: contain; background: #000; }
|
|||||||
background: var(--color-room-tile);
|
background: var(--color-room-tile);
|
||||||
color: var(--color-room-text-primary);
|
color: var(--color-room-text-primary);
|
||||||
}
|
}
|
||||||
.tb-btn span.label { font: var(--text-caption); text-transform: none; letter-spacing: normal; color: var(--color-room-text-secondary); font-weight: 500; }
|
.tb-btn span.label {
|
||||||
|
font: var(--text-caption);
|
||||||
|
font-size: clamp(11px, calc(11px + (100vw - 600px) * 1 / 600), 12px);
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
color: var(--color-room-text-secondary);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
.tb-btn:hover .icon-shell { background: var(--color-room-tile-hover); }
|
.tb-btn:hover .icon-shell { background: var(--color-room-tile-hover); }
|
||||||
|
|
||||||
|
/* Короткая подпись мини-окна (см. RoomToolbar.tsx) — «Мини-окно» на узком
|
||||||
|
экране переносится на 2 строки и делает эту кнопку выше соседних; ниже
|
||||||
|
порога, где начинается перенос, прячем длинный вариант и показываем
|
||||||
|
короткий «Мини» — кнопка остаётся однострочной и той же высоты, что и
|
||||||
|
остальные. */
|
||||||
|
.tb-btn .label-short { display: none; }
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.tb-btn .label-full { display: none; }
|
||||||
|
.tb-btn .label-short { display: inline; }
|
||||||
|
}
|
||||||
|
|
||||||
.tb-btn.is-off .icon-shell { background: var(--color-room-mic-off); border-color: var(--color-room-mic-off); color: #3a0f16; }
|
.tb-btn.is-off .icon-shell { background: var(--color-room-mic-off); border-color: var(--color-room-mic-off); color: #3a0f16; }
|
||||||
.tb-btn.is-off span.label { color: var(--color-room-mic-off); font-weight: 700; }
|
.tb-btn.is-off span.label { color: var(--color-room-mic-off); font-weight: 700; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user