Files
vidconf/design/mockups/dark/README.md
Max Ronzhin 8757bec8ac
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
first commit
2026-07-23 02:38:05 +03:00

189 lines
18 KiB
Markdown
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.
# VidConf — тёмные варианты оболочки
Обязательный референс для разработки.
Тёмная тема для экранов «оболочки» (auth/лобби/календарь/join/«мои
конференции»/админка), реализована **поверх** дизайн-системы, а не взамен
неё. `design/tokens.css` и `design/DESIGN_SYSTEM.md` — единственный
источник истины по значениям (см. §0 `DESIGN_SYSTEM.md`: «светлая тема —
оболочка (со светлым/тёмным вариантом), тёмная — комната конференции
всегда»). Реализация во frontend — `frontend/src/hooks/useTheme.ts` и
`frontend/src/components/ui/ThemeToggle.tsx` (см. `frontend/README.md`,
раздел «Темы оболочки»).
## Что здесь
Разметка, контент и русские данные каждого файла — 1:1 копия
соответствующего светлого макета из `design/mockups/`. Меняется только
цветовая схема: вместо индиго-на-белом (`referens.png`) — графит-мята-роза-
янтарь той же гаммы, что уже утверждена для комнаты конференции
(`collor_ico.png`, токены `[data-theme="room"]` в `tokens.css`).
| Файл | Светлый прообраз | Экран |
|---|---|---|
| `login.html` | `../auth.html` | Вход / регистрация / подтверждение email |
| `lobby.html` | `../lobby.html` | Лобби — хаб действий 2×2 |
| `calendar.html` | `../calendar.html` | Календарь-менеджер конференций (+ создание/редактирование/отмена) |
| `join.html` | `../join.html` | Подключение по ссылке/номеру → представиться (гость) → пароль |
| `my-conferences.html` | `../my-conferences.html` | Мои конференции |
| `admin.html` | `../admin.html` | Админка (конференции, пользователи, рассылка приглашений) |
`room.html` и `email-summary.html` в комплект не входят: комната уже тёмная
(эталон гаммы), а письмо-саммари по правилам проекта всегда светлое
(почтовые клиенты не гарантируют поддержку тёмной темы/CSS-переменных).
Ссылки на «Войти»/«Создать» из `lobby.html`/`my-conferences.html` ведут на
уже существующий `../room.html`; ссылка «Открыть саммари» — на
`../email-summary.html`.
Каждый файл самодостаточен: встроенный `<style>`, инлайн-SVG-иконки
(lucide-совместимые контуры), без CDN и внешних сетевых зависимостей —
открывается двойным кликом. Единственная локальная зависимость —
`<link rel="stylesheet" href="../../tokens.css">` (тот же приём, что и в
светлых макетах: используются базовые не-цветовые токены — spacing, радиусы,
типографика, тени-заготовки, шрифты).
## Переключатель темы
В шапке каждого макета — сегментированный переключатель ☀ / 🌙 (иконки
`Sun`/`Moon`, lucide-стиль), «Тёмная» — активный сегмент. Элемент
статичный (демонстрирует точку входа в реальный toggle, не переключает
тему по клику в макете) и размещён:
- `login.html` — плавающей плашкой в правом верхнем углу (у экрана нет
общего топбара, панель бренда/форма — раздельные колонки);
- `lobby.html`, `calendar.html`, `my-conferences.html` — внутри правой
группы топбара, рядом с меню пользователя;
- `join.html` — в топбаре, справа от логотипа;
- `admin.html` — в шапке сайдбара, рядом с логотипом.
## Как получена палитра
### Принцип
Тёмная схема **не изобретает новых цветов**, а переиспользует уже
утверждённые токены комнаты конференции (`tokens.css`, блок
`[data-theme='room']`, см. `DESIGN_SYSTEM.md` §1.2) в новых ролях — так
оболочка и комната читаются как одна система, когда пользователь входит
из тёмного лобби в тёмную комнату. Все переопределения делаются одним
блоком `:root { … }` в начале `<style>` каждого файла — он перекрывает
одноимённые переменные `:root` из `tokens.css` (та же специфичность,
позже в источнике — выигрывает), поэтому весь остальной CSS ниже —
дословная копия светлого макета и автоматически перекрашивается.
### Токены, переиспользованные из комнаты 1:1 (без изменения hex)
| Токен оболочки (dark) | = токен комнаты | Hex | Новая роль в оболочке |
|---|---|---|---|
| `--color-bg` | `--color-room-bg` | `#1E1E1E` | фон страницы |
| `--color-surface` | `--color-room-surface` | `#2A2A2A` | карточки, топбар, поля |
| `--color-border` | `--color-room-tile-border` | `#3F3F3F` | базовая обводка |
| `--color-ink-900` | `--color-room-text-primary` | `#E8E8E8` | основной текст |
| `--color-ink-500` | `--color-room-text-secondary` | `#B0B0B0` | вторичный текст |
| `--color-ink-300` | `--color-room-text-tertiary` | `#7A7A7A` | плейсхолдеры/disabled |
| `--color-ink-700`, `--color-accent`, `--color-border-pill`, `--color-success`, `--color-success-dot` | `--color-room-mic-on` | `#7FDDA8` | мята: бренд/заголовки/ссылки/CTA/«успех» — единый пастельно-зелёный вектор (см. ниже) |
| `--color-danger`, `--color-danger-dot` | `--color-room-mic-off` | `#EB93A1` | розово-красный: текст/иконки/обводка статуса «отменена»/ошибки |
| `--color-warning`, `--color-warning-dot` | `--color-room-speaker-ring` | `#D6A83D` | янтарь: статус «запланирована» |
| `--color-focus-ring` | `--color-room-focus-ring` | `#D6A83D` | кольцо `:focus-visible` — то же значение, что и в комнате |
| `--color-danger-solid` | `--color-room-danger-bg` | `#B85468` | заливка **сплошных** danger-кнопок (см. ниже, почему это отдельный токен) |
| `--color-danger-solid-hover` | `--color-room-danger-bg-hover` | `#B9495F` | hover сплошной danger-кнопки |
**Одна мята — три роли.** В светлой оболочке бренд-индиго (`--color-ink-700`,
заголовки/ссылки/обводка pill-кнопок) и мятный CTA (`--color-accent`) — два
разных токена с разными hex. В комнате пастельная мята уже одна на всё
«позитивное» (`--color-room-mic-on` = «микрофон включён» + активная
демонстрация экрана + счётчик участников + кнопка отправки в чате). Чтобы
не завозить в тёмную оболочку новый, ничем не подкреплённый в комнате
оттенок, `--color-ink-700` и `--color-accent` в тёмной оболочке **сведены
к одному и тому же** `#7FDDA8` — бренд, заголовки, ссылки, обводка
secondary-кнопок и заливка CTA используют один и тот же «фирменный» зелёный.
Различие ролей (бренд-текст vs интерактивная заливка) остаётся читаемым за
счёт контекста (текст vs заливка с тёмным текстом поверх), а не за счёт
второго оттенка — это соответствует прецеденту самой комнаты.
**Почему заливка danger-кнопок — отдельный токен, а не `--color-danger`.**
В светлой теме один hex (`#C7364F`) одинаково хорошо работает и как текст на
белом, и как заливка кнопки с белым текстом (тёмный, насыщенный тон). В
тёмной теме эти две роли расходятся: `--color-room-mic-off` (`#EB93A1`) —
светлый пастельный тон, читаемый как **текст на тёмном фоне** (6.30:1 на
`#2A2A2A`), но слишком светлый, чтобы на нём читался белый текст кнопки
(≈1.9:1, провал). Поэтому для сплошных danger-кнопок (`.btn-danger`
«Отменить все повторения» в календаре, «Удалить» в админке) заведена
отдельная пара `--color-danger-solid` / `--color-danger-solid-hover`,
переиспользующая уже готовые `--color-room-danger-bg(-hover)` (`#B85468` /
`#B9495F`, задокументированы в `DESIGN_SYSTEM.md` §1.2 с контрастом
4.66:1/5.02:1 для белого текста).
### Новые токены (введены только там, где у комнаты нет готового аналога)
Комната — экран без брендинга, форм и многошаговых карточек, поэтому под
нужды оболочки понадобилось несколько новых значений. Все получены
подмешиванием уже утверждённых цветов комнаты к графитовому фону/друг к
другу (не независимо придуманные тона), проверены по WCAG 2.1 (см. расчёт
ниже, тот же метод, что в `design/tools/contrast.py`):
| Токен | Hex | Как получен | Контраст | Роль |
|---|---|---|---|---|
| `--color-bg-alt` | `#242424` | между `--color-room-bg` (`#1E1E1E`) и `--color-room-surface` (`#2A2A2A`) | — | альт-фон секций, инпуты, disabled-поля |
| `--color-border-strong` | `#585858` | осветление `--color-border` | 2.02:1 на surface (нетекст, декоративный hover-акцент — дублируется тенью/курсором, не единственный носитель состояния) | обводка при hover |
| `--color-ink-400` | `#5D9A78` | мята `#7FDDA8` × фон `#1E1E1E`, смешение 35% | 5.05:1 на bg / 4.35:1 на surface | эйбрау-подписи `[ В СКОБКАХ ]`, крупные подписи (аналог ⚠︎ large-text-only из светлой темы, но с запасом) |
| `--color-accent-hover` | `#75CA9A` | мята × фон, смешение 10% | текст `#10331F` на заливке: 7.04:1 | hover CTA |
| `--color-accent-active` | `#6CB78C` | мята × фон, смешение 20% | текст `#10331F` на заливке: 5.80:1 | active/pressed CTA |
| `--color-accent-text` | `#10331F` | **не новый** — переиспользован буквальный hex, уже встречающийся инлайн в `room.html` (`.chat-input-row button`, `.tb-btn.is-positive-active`, `.badge-count`) как цвет текста на заливке `--color-room-mic-on` | 8.45:1 на мяте | текст на CTA/бренд-заливках мятой |
| `--color-success-bg` | `rgba(127,221,168,.14)` | мята с низкой непрозрачностью поверх тёмной поверхности | — | подложка бейджей «идёт сейчас»/«свободна»/«активен» |
| `--color-danger-bg` | `rgba(235,147,161,.14)` | розовый (mic-off) с низкой непрозрачностью | — | подложка бейджей «отменена» |
| `--color-warning-bg` | `rgba(214,168,61,.16)` | янтарь (speaker-ring) с низкой непрозрачностью | — | подложка бейджей «запланирована» |
| `--shadow-sm/md/lg/glass` | `rgba(0,0,0,.35.5)` | по образцу `--shadow-room-panel` комнаты (тёмные тени вместо индиго-тонированных) | — | тени карточек/модалок/glass-панелей |
Контраст всех текстовых пар проверен по формуле WCAG 2.1 — пары, использованные
в макетах (основной текст, вторичный текст, мята/роза/янтарь как текст на
`bg`/`surface`/`tile`, белый текст на `--color-danger-solid`), все дают
≥ 4.5:1 (текст) либо ≥ 3:1 (декоративные элементы, статус которых также
задублирован иконкой/текстом — см. правило §5 `DESIGN_SYSTEM.md`). Регрессия
этих пар — в `design/tools/contrast.py`.
## Точечные правки поверх скопированного CSS
Для каждого файла CSS светлого макета скопирован дословно (все `.class`
правила без изменений) — перекраска идёт только через блок `:root`. Ручных
точечных правок пять видов, во всех случаях — потому что исходное правило
использовало **литеральный hex/rgba**, а не `var()`, и не могло
перекраситься автоматически:
1. **Аватары и `.weekday-chip.is-selected`/`.badge-role-admin`** — в
светлой теме заливка `var(--color-ink-700)` (тёмный индиго) сочеталась с
жёстким `color: #fff`. Так как `--color-ink-700` теперь = мята (светлый
тон), белый текст перестаёт читаться (≈1.9:1) — заменено на
`var(--color-accent-text)` (`#10331F`, 8.45:1 на мяте).
2. **`.btn-danger`** (`calendar.html`, `admin.html`) — добавлена отдельная
заливка `var(--color-danger-solid)` вместо `var(--color-danger)` (см.
таблицу выше); белый текст кнопки не менялся.
3. **`.copy-toast`** (`my-conferences.html`) — фон был `var(--color-ink-900)`
(тёмный в светлой теме → стал бы светло-серым в тёмной, ломая тёмный
тултип); заменён на буквальный `#333333` (= `--color-room-surface-raised`),
текст остаётся `var(--color-ink-900)` (теперь светлый) — тултип снова
тёмный чип со светлым текстом.
4. **Декоративные градиенты/rgba-подложки** (`login.html`
`.brand-panel`/`.brand-panel::after`, `lobby.html` фон `body`,
`calendar.html` `.day-col.is-today`/`.cancel-alert`, `login.html`/
`join.html`/`calendar.html` box-shadow фокуса и ошибки, glass-обводка
`rgba(255,255,255,.7)` в `login.html`/`admin.html`, disabled-заливка
кнопок) — старые rgba были построены на индиго/старом danger-hex;
заменены на тональные аналоги новой палитры (мятное свечение вместо
индигового/мятного на белом, янтарный focus-glow вместо индигового,
розовый error-glow, `rgba(255,255,255,.08)` вместо `.7` для тёмного
стекла).
5. **`color-scheme: dark`** добавлен в блок `:root`, чтобы нативные
элементы форм (скроллбар, чекбоксы без кастомной стилизации) тоже
рендерились в тёмной палитре браузера.
## Доступность (проверено при подборе палитры)
- Текст ≥ 4.5:1 везде, кроме крупных/декоративных элементов (аналогично
правилу §5 `DESIGN_SYSTEM.md` для светлой темы, порог 3:1).
- Статус не передаётся только цветом: бейджи конференций — иконка + текст
(как в светлой теме), «скопировано» — смена иконки `Copy → Check` +
текстовый тултип, ошибки полей — иконка `AlertCircle` + текст под полем,
`:focus-visible` — везде видимое кольцо (`--color-focus-ring`, тот же
янтарь, что и в комнате).
- Палитра пастельная (мята/роза/янтарь той же светлоты, что уже утверждена
для комнаты), неоновых/кислотных акцентов не вводилось.