Files
senboost/design.md
T

343 lines
27 KiB
Markdown
Raw Permalink 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.
# Дизайн-документ — Forgetting
Тёплая фиолетово-кремовая палитра в системе ролей Material 3.
Настроение: спокойный, премиальный, чуть «бутиковый» интерфейс — не типичный холодный «техно».
Документ единый и покрывает обе платформы. **Часть I (основы)** — палитра, роли, типографика, формы, состояния, доступность, тёмная тема — одинакова для десктопа и мобильного. **Часть II** описывает общий язык компонентов. **Части III и IV** — компоновку, которая на платформах различается. Язык дизайна один; меняется только раскладка.
---
# Часть I. Основы (общие для десктопа и мобильного)
## 1. Палитра
### Базовые цвета
| Назначение | HEX | Заметка |
| ------------------------ | --------------------- | --------------------------------------------------------- |
| Фиолетовый (акцент) | `#a96bff` | HSL 275°, 100%, 71% — светлый, для тёмной темы и акцентов |
| Фиолетовый (основной) | `#6a45b8` | тон ~40 — заливка кнопок, активные элементы |
| Тёмно-фиолетовый (текст) | `#5a2da8` | текст на светло-фиолетовом контейнере |
| Крем (фон) | `#faf6f0` | основная поверхность |
| Крем (исходный) | `#f6f0ea` / `#ece0d1` | более тёплые/тёмные оттенки нейтрала |
| Оранжевый (исходный) | `#ffb76b` | стартовый цвет, ушёл в роль `tertiary` |
### Связь оттенков
Крем `#ece0d1` (тон ~33°) и оранжевый `#ffb76b` (тон ~31°) — родственники по тёплому углу спектра.
Фиолетовый — холодный акцент в противовес тёплому нейтралу. Отсюда баланс «тёплая база + прохладный акцент».
---
## 2. Роли Material 3
| Роль MD3 | Светлая тема | Текст на ней (`on-`) |
| ------------------------------- | ------------ | -------------------- |
| `primary` | `#6a45b8` | `#ffffff` |
| `primary-container` | `#ebddff` | `#5a2da8` |
| `secondary-container` | `#ebddff` | `#5a2da8` |
| `tertiary-container` | `#ffdcad` | `#7a4a14` |
| `surface` | `#faf6f0` | `#3a2e22` |
| `surface-container` | `#f0e8dd` | `#3a2e22` |
| `surface-container-high` | `#ece2d3` | `#3a2e22` |
| `surface-bright` (рабочая зона) | `#fdfaf6` | `#3a2e22` |
| `outline` | `#d8cdbe` | — |
| `outline-variant` | `#ece2d3` | — |
| `error` | `#ba1a1a` | `#ffffff` |
| `error-container` | `#ffdad6` | `#410002` |
### Статусные цвета (тёплый подтон)
| Статус | Фон чипа | Текст | Точка |
| ----------------- | --------- | --------- | --------- |
| Онлайн / успех | `#c0dd97` | `#2c4d0a` | `#639922` |
| Офлайн / нейтраль | `#e4dac9` | `#7a6a55` | `#a99a85` |
| Ошибка | `#ffdad6` | `#410002` | `#ba1a1a` |
> Принцип: `primary` (тёмный `#6a45b8`) — для заливок и текста по контрасту.
> Светлый `#a96bff` держим как акцент/иконки/тёмную тему, не как фон под белый текст.
---
## 3. Типографика
- Один шрифт без засечек на весь интерфейс (system-ui / Inter / Roboto).
- Два веса: 400 (обычный) и 500 (акцент). Без 600–700.
- **Sentence case** везде, в том числе в заголовках таблиц. Без Title Case и КАПСА.
- Моноширинный шрифт для технических данных: IP-адреса, VPN-ключи, rx/tx.
Шкала:
| Элемент | Размер | Вес |
| -------------------------------- | ------- | --- |
| Заголовок раздела | 20px | 500 |
| Подзаголовок / название карточки | 15–16px | 500 |
| Основной текст | 14px | 400 |
| Заголовки таблицы | 13px | 500 |
| Данные таблицы | 13px | 400 |
| Подписи / hint | 12px | 400 |
---
## 4. Скругления (MD3 shape scale)
| Элемент | Радиус |
| ---------------------------------- | ------- |
| Кнопки, чипы, инпуты (pill) | `100px` |
| Карточки / контейнеры | `24px` |
| Внутренние блоки таблицы / метрики | `16px` |
| Иконка-логотип | `8–9px` |
| Аватар, точка статуса | `50%` |
> Скругления только полные (по всем сторонам). Односторонних бордюров с radius не делаем.
---
## 5. Состояния и взаимодействие (MD3 state layers)
Поверх элемента — полупрозрачный слой акцентного цвета:
- Hover: ~8% непрозрачности.
- Focus / pressed: ~12%.
- Для фиолетовых элементов слой фиолетовый, для нейтральных — тёмный нейтрал.
Элевация — через тональные поверхности (светлее/темнее крем), а не через тени. Иерархия строится тональностью: рабочая зона данных светлее крема, крем — для фона и хрома.
**Опора на платформу.**
- На десктопе (указатель) hover-слой работает как первичная обратная связь.
- На тач-устройствах hover не срабатывает — обратная связь строится на нажатии и выборе, не на наведении.
**Инертные vs действенные элементы.**
- Навигационные строки и статичные строки данных — **инертны** (без эффекта вдавливания); активное состояние показывается заливкой-таблеткой (`primary-container`).
- Реальные действия (кнопки, переключатель, QR, удаление) могут иметь лёгкий pressed-эффект через state layer акцентного цвета (~12%).
---
## 6. Доступность
- Контраст фиолетового `#a96bff` на креме ≈ 2,6:1 — годится только для крупных элементов; для мелкого текста по фиолетовому брать `#5a2da8` или темнее (≥ 4,5:1).
- Основной текст всегда тёмно-коричневый `#3a2e22`, не чисто чёрный и не фиолетовый. Светлый акцентный фиолетовый под мелкий текст не использовать.
- Минимальный размер шрифта — 12px; технические данные (IP, ключи, rx/tx) — моноширинным.
- Тач-таргеты ≥ 44px (кнопки действий, гамбургер, переключатель, пункты меню).
- Иконки-кнопки без подписи получают доступное имя (`aria-label`): меню, удаление и т.п.
- Один шрифт, два веса (400 / 500), sentence case везде.
---
## 7. Тёмная тема
Крем в тёмную тему не переносится — нужен отдельный набор. Направление — **тёплый уголь**: тёмные поверхности с тем же тёплым нейтральным подтоном, что и крем в светлой теме (тон ~30–40°), а не баклажановые. Так фирменный баланс «тёплая база + прохладный фиолетовый акцент» сохраняется и в темноте: акцент остаётся холодным фиолетовым на тёплой тёмной базе, как и в светлой.
Фиолетовый акцент — общий со светлой темой по смыслу, но осветлён под тёмный фон.
| Роль | Тёмная тема | Текст на ней (`on-`) |
| ------------------------------- | ------------------------------ | -------------------- |
| `surface` | `#1a1611` | `#ede2d4` |
| `surface-container` | `#251f18` | `#ede2d4` |
| `surface-container-high` | `#302820` | `#ede2d4` |
| `surface-bright` (рабочая зона) | `#2b251d` | `#ede2d4` |
| `primary` | `#cbb3ff` (светлый фиолетовый) | `#381b6c` |
| `primary-container` | `#52389e` | `#ebddff` |
| `secondary-container` | `#483a55` | `#ebddff` |
| `outline` | `#4d4334` | — |
| `outline-variant` | `#342c20` | — |
| `error` | `#ffb4ab` | `#5c1414` |
| `error-container` | `#5c1414` | `#ffb4ab` |
| текст / `on-surface` | `#ede2d4` | — |
| приглушённый текст | `#b6a994` | — |
### Статусные цвета (тёмная тема)
Фон и текст осветлены/переинвертированы под тёмный фон, подтон тот же тёплый.
| Статус | Фон чипа | Текст | Точка |
| ----------------- | --------- | --------- | --------- |
| Онлайн / успех | `#2d4413` | `#c8e3a0` | `#8fc24f` |
| Офлайн / нейтраль | `#34291c` | `#d0c0a4` | `#b0a085` |
| Ошибка | `#5c1414` | `#ffb4ab` | `#ff5449` |
> Значения — рабочая отправная точка. Контраст текста на поверхностях стоит прогнать через проверку (цель ≥ 4,5:1 для мелкого текста) перед фиксацией.
>
> Альтернатива на будущее: «баклажан» — поверхности тонируются фиолетовым (`surface` `#18121d`, `container` `#221a29`, `bright` `#2a2031`, текст `#ece0e9`, приглушённый `#b3a4bd`, `outline` `#4c4356`). Каноничный MD3-путь, звучит «премиальнее», но база уходит в холодный тон.
---
# Часть II. Компоненты (общий язык)
Эти компоненты используют одни и те же роли на обеих платформах; различается только их расположение в раскладке.
### Кнопки
- **Главное действие** (Создать пользователя): заливка `primary` `#6a45b8`, текст белый (`on-primary`), pill.
- **Вторичное** (Обновить): tonal — фон `secondary-container` `#ebddff`, текст `#5a2da8`, pill.
- **Опасное** (Выход, удаление): контур `#e6c4bc` / роль `error`, текст `#b34a3a`, без заливки, pill.
- Иконка слева от текста, gap 6–8px.
### Поля ввода и поиска
- Pill-инпут, фон `surface-bright` `#fdfaf6`, бордюр `outline` `#d8cdbe`, плейсхолдер приглушённым.
- Поле поиска — с иконкой поиска слева.
### Чипы статуса
- Pill, маленькая цветная точка + подпись. Цвета — из таблицы статусов (успех / нейтраль / ошибка), текст соответствующей роли `on-`.
---
# Часть III. Десктоп
### Компоновка
- Многоколоночная сетка.
- Заголовок раздела — в шапке контента.
### Боковое меню (постоянная панель)
- Фиксированная ширина ~240px, всегда на экране.
- Фон `#f0e8dd` (`surface-container`, на тон темнее основного — мягкое разделение без жёсткой границы).
- Логотип сверху, навигация ниже, «Выход» прижат к низу (`margin-top: auto`).
- Активный пункт: pill-контейнер `#ebddff` (`primary-container`) + текст `#5a2da8`.
- Неактивные: текст `#5a4a3a`, при наведении — лёгкая фиолетовая подсветка (state layer).
### Таблица пользователей
- Контейнер `surface-bright` `#fdfaf6`, скругление 16px, бордюр `#ece2d3` (`outline-variant`).
- Шапка на тоне `#f0e8dd`, текст среднего веса `#5a4a3a`.
- Разделители строк — `0.5px solid #ece2d3`.
- Колонки: `#`, Статус, Имя, IP, rx, tx, действия.
- IP и Key — моноширинным; длинный ключ обрезаем многоточием.
- Действия — иконки: копировать `#8a6bff`, удалить `#b34a3a`.
---
# Часть IV. Мобильный
## 1. Принципы адаптации
1. Одна колонка. Контент течёт вертикально на ширине телефона (рабочая ширина ~360px, поля по 16px).
2. Никаких таблиц с горизонтальной прокруткой — табличные данные разворачиваются в карточки.
3. Боковое меню десктопа превращается в модальный navigation drawer (паттерн Material 3).
4. Главное действие всегда в зоне большого пальца — кнопки полноширинные или парные, высота тача ≥ 44px.
5. Те же роли поверхностей и те же shape-токены, что на десктопе. Меняется компоновка, не язык дизайна.
## 2. Навигация и drawer
### Модель
Приложение имеет один основной раздел («Пользователи»). На десктопе это постоянная боковая панель ~240px; на мобильном — **модальный drawer**, скрытый по умолчанию.
### Открытие и закрытие (важно по MD3)
- Открытие — **только тапом по иконке-гамбургеру** в верхнем баре.
- Закрытие — тап по затемнению (scrim) или свайп панели к её левому краю (срабатывает при сдвиге ~40px+).
- Открытие edge-swipe'ом от края экрана **не используется**: жест конфликтует с системным «назад» (predictive back) на Android.
### Поведение
- Drawer выезжает слева, поверх контента, с затемнением под ним.
- Затемнение блокирует взаимодействие с экраном, пока панель открыта.
- Анимация — горизонтальный сдвиг панели + плавное появление scrim (быстрый, «решительный» easing, ~250–280 мс); затемнение и сдвиг анимируются вместе.
### Содержимое панели
Поверхность панели — `surface-container` (на тон темнее основного экрана), мягкое разделение без жёсткой границы. Скругление контейнера 24px, правые углы.
Сверху вниз:
1. **Шапка** — вордмарк приложения (роль заголовка) + версия (роль приглушённого текста), внутренний отступ.
2. **Тонкий разделитель** (`outline`, 0.5px).
3. **Навигация** — пункты-строки с ведущей иконкой 22px и подписью 15px, gap 16px.
- Активный пункт: pill-контейнер `primary-container` во всю ширину; текст, иконка и счётчик — `on-primary-container`, вес 500.
- Неактивный пункт: подпись и иконка — основной текст (тёмный нейтрал), без подсветки при наведении.
- Строки навигации **инертны при нажатии** — без эффекта вдавливания, выделяет только активное состояние.
4. **«Выход»** — прижат к низу (`margin-top: auto`), стиль опасного действия (контур, без заливки), pill, иконка слева.
### Замечание про объём меню
Длинный список разделов (как у Gmail-паттерна) оправдан только при 5+ назначениях. У приложения раздел один, поэтому drawer минимальный: шапка → активный пункт → «Выход» внизу. Доп. пункты добавляются только под реальные экраны.
## 3. Верхний бар (top app bar)
- Слева — иконка-гамбургер (кнопка-таргет ≥ 42px, круглая зона нажатия).
- Рядом — заголовок раздела (роль заголовка, 20px / 500).
- Бар без заливки и без тени; высота поверхности задаётся фоном экрана (`surface`).
## 4. Экран «Пользователи»
Порядок блоков сверху вниз: верхний бар → карточка сервера → «Добавить сервер» → форма создания → счётчик → список пользователей.
### 4.1. Карточка VPN-сервера
- Поверхность — `surface-bright`, скругление 24px.
- **Активная обводка** — рамка 2px роли `primary` (приглушённый светло-фиолетовый вариант): сигнал, что сервер выбран/активен.
- Слева — компактный **переключатель** (pill-трек, маленький круглый ползунок). Состояние «вкл» отражается цветом трека из роли статуса «успех» и положением ползунка.
- По центру — название сервера (роль подзаголовка, 16px / 500) и IP **моноширинным** (роль приглушённого текста).
- Справа — нейтральный чип счётчика пиров (роль статуса «нейтраль», pill).
### 4.2. «Добавить сервер»
- Полноширинная кнопка-«призрак»: пунктирный контур (`outline`), без заливки, иконка `+` слева, приглушённый текст. Pill (100px).
### 4.3. Форма создания пользователя
- Поле ввода: pill-инпут на `surface-bright`, бордюр `outline`, плейсхолдер приглушённым. Полная ширина.
- Под ним пара кнопок в ряд (50/50):
- **Создать** — главное действие: заливка `primary`, текст `on-primary`, иконка `+`, pill.
- **Обновить** — вторичное: tonal (`secondary-container` / `on-secondary-container`), иконка обновления, pill.
### 4.4. Список пользователей
- Над списком — счётчик («N пользователей») приглушённым текстом 12px.
- Десктопная таблица (`#`, Статус, Имя, IP, rx, tx, действия) на мобильном **разворачивается в карточки** — по одной на пользователя.
### 4.5. Карточка пользователя
Поверхность `surface-bright`, бордюр `outline-variant`, скругление 24px. Внутри:
1. **Верхняя строка** — слева порядковый `#N` (приглушённый) + имя (16px / 500); справа чип статуса «онлайн» (роль статуса «успех»: точка + подпись, pill).
2. **Строка IP** — иконка-глобус + адрес моноширинным.
3. **Два блока метрик** (rx / tx) в ряд 50/50: внутренние блоки на `surface-container`, скругление 16px. Сверху подпись со стрелкой (↓ rx / ↑ tx) приглушённым 12px, под ней значение моноширинным 18px / 500.
4. **Действия** — ряд: кнопка «QR» (контур `outline`, иконка QR акцентным фиолетовым) на всю доступную ширину + квадратная кнопка удаления (контур роли «ошибка», иконка корзины — `error`).
## 5. Сводка мобильных компонентов (через роли и токены)
| Компонент | Поверхность / контур | Форма | Текст |
| --------------------- | -------------------------------------- | ---------- | --------------------------- |
| Карточка сервера | `surface-bright` + рамка `primary` 2px | 24px | подзаголовок + mono |
| Карточка пользователя | `surface-bright` + `outline-variant` | 24px | подзаголовок + mono |
| Блок метрики (rx/tx) | `surface-container` | 16px | подпись + mono |
| Кнопка «Создать» | заливка `primary` | pill 100px | `on-primary`, 500 |
| Кнопка «Обновить» | tonal `secondary-container` | pill 100px | `on-…`, 500 |
| «Добавить сервер» | пунктир `outline` | pill 100px | приглушённый |
| «Выход» | контур (опасное) | pill 100px | роль опасного |
| Поле ввода | `surface-bright` + `outline` | pill 100px | основной / плейсхолдер |
| Чип статуса | роль статуса (успех/нейтраль/ошибка) | pill 100px | соответствующий `on-` |
| Активный пункт меню | `primary-container` | pill 100px | `on-primary-container`, 500 |
---
# Отличия десктоп / мобильный (кратко)
| Аспект | Десктоп | Мобильный |
| -------------------- | -------------------------------- | ---------------------------------- |
| Навигация | постоянная боковая панель ~240px | модальный drawer (гамбургер) |
| Список пользователей | таблица с колонками | карточки, по одной на пользователя |
| rx / tx | ячейки таблицы | два блока-метрики внутри карточки |
| Действия в строке | иконки в конце строки | ряд кнопок внизу карточки |
| Ширина | многоколоночная сетка | одна колонка, поля 16px |
| Заголовок раздела | в шапке контента | в верхнем баре рядом с гамбургером |
---
# Принципы (итог)
1. Тёплая база + прохладный фиолетовый акцент. Один язык дизайна на обеих платформах — меняется компоновка, не палитра.
2. Цвет кодирует смысл (статус, действие), а не порядок.
3. Иерархия — тональностью поверхности, не тенями. Рабочая зона данных светлее (почти белая), крем — для фона и хрома.
4. Sentence case, два веса шрифта, без капса. Технические данные — моноширинным.
5. Главное действие — залито фиолетовым; вторичное — tonal; опасное — контур.
6. Таблицы → карточки, rx/tx → блоки-метрики на мобильном; одна колонка, крупные тач-таргеты, действия в зоне большого пальца.
7. Drawer открывается гамбургером, закрывается scrim/свайпом; edge-swipe не задействуем. Hover — опора десктопа; на тач-устройствах обратная связь на нажатии/выборе.