27f349550c
- sketches/index.html: все экраны одним документом в порядке 1·… (14–19 — бывшие approved) - approved/ (4 файла групп + 3 макета + README) удалён как дубль - стили вынесены в sketches/style.css - README, THEMES, BORROW-FROM-ASSISTENT, MARKDOWN-SOURCE, MIC-ASR-SEARCH приведены к фактическому состоянию
175 lines
11 KiB
Markdown
175 lines
11 KiB
Markdown
# Цветовые темы: цвета не пишем в коде
|
||
|
||
**Правило:** в коде **не должно быть цветов числами**. Цвет берётся из текущей
|
||
цветовой схемы по смыслу. Тем будет **несколько** (тёмная, светлая и другие),
|
||
и одна и та же деталь интерфейса должна выглядеть правильно в каждой.
|
||
|
||
**Почему так:** если цвет вписан числом, при смене темы он останется прежним —
|
||
и на светлом фоне окажется тёмно-серый текст, тёмная тень или невидимая граница.
|
||
Такие места обычно находят уже у пользователя.
|
||
|
||
---
|
||
|
||
## Как это выглядит в коде
|
||
|
||
### Неправильно
|
||
|
||
```kotlin
|
||
Text(
|
||
text = "Диалоги",
|
||
color = Color(0xFFEBEBEB), // цвет вписан числом
|
||
modifier = Modifier.background(Color(0xFF17212B)) // и здесь тоже
|
||
)
|
||
```
|
||
|
||
При смене темы этот текст останется белым, а панель — тёмно-синей. В светлой
|
||
теме получится белое на белом.
|
||
|
||
### Правильно
|
||
|
||
```kotlin
|
||
Text(
|
||
text = "Диалоги",
|
||
color = MaterialTheme.colorScheme.onSurface,
|
||
modifier = Modifier.background(MaterialTheme.colorScheme.surface)
|
||
)
|
||
```
|
||
|
||
Здесь сказано **что это по смыслу**: текст «на поверхности» и сама «поверхность».
|
||
Какие именно цвета — решает схема, а не код.
|
||
|
||
---
|
||
|
||
## Имена по смыслу, а не по виду
|
||
|
||
| Хорошо (по смыслу) | Плохо (по виду) |
|
||
|---|---|
|
||
| `surface` — поверхность | `darkBlue` — тёмно-синий |
|
||
| `onSurface` — текст на поверхности | `almostWhite` — почти белый |
|
||
| `primary` — главный акцент | `blue` — синий |
|
||
| `error` — ошибка | `red` — красный |
|
||
| `outline` — границы | `greyLine` — серая линия |
|
||
|
||
Смысл от смены темы не меняется, а название цвета — меняется. `darkBlue`
|
||
в светлой теме станет ложью в самом названии.
|
||
|
||
---
|
||
|
||
## Что именно берётся из схемы
|
||
|
||
Проверять надо **все** цвета, а не только текст с фоном. Чаще всего забывают:
|
||
|
||
- **границы** — `outline`, `outlineVariant`;
|
||
- **фон «наведения» курсора** и **выбранной строки**;
|
||
- **тени** вокруг окон;
|
||
- **затемнение** под окном (полупрозрачное чёрное — тоже цвет);
|
||
- **цвет неактивного текста** — подписи, время, пояснения;
|
||
- **цвет состояния** — «на связи» зелёным, «не отвечает» красным;
|
||
- **фон поля ввода** и его рамку при фокусе;
|
||
- **цвет значков** и кружка непрочитанных;
|
||
- **фон блока кода** и **цвет ссылок** в ответах ассистента;
|
||
- **полосы прокрутки**;
|
||
- **выделение текста мышью**.
|
||
|
||
Если деталь где-то не переключилась — она выбивается и её видно сразу.
|
||
|
||
---
|
||
|
||
## Особый случай: цвета для различения ассистентов
|
||
|
||
**Эти цвета из схемы не берутся.** Пользователь задаёт их сам в настройках, чтобы
|
||
отличать ассистентов друг от друга. Они заданы сознательно и в другой теме
|
||
остаются собой — иначе различие пропадёт.
|
||
|
||
То есть в клиенте **два разных типа цвета**, и путать их нельзя:
|
||
|
||
| Тип | Откуда | Меняется ли с темой |
|
||
|---|---|---|
|
||
| Цвета интерфейса | Из цветовой схемы | **Да** |
|
||
| Цвет или картинка ассистента | Заданы пользователем | **Нет** |
|
||
|
||
**Практический вывод:** там, где подставляется цвет ассистента, нельзя брать
|
||
`MaterialTheme.colorScheme.*` — нужен именно пользовательский цвет. И наоборот:
|
||
фон строки диалога берётся из схемы, даже если рядом стоит цветная полоска агента.
|
||
|
||
**Ещё следствие:** пользовательский цвет должен **читаться** на фоне любой темы.
|
||
Пять предложенных цветов подобраны под тёмную тему; в светлой какие-то могут
|
||
оказаться бледными. Это надо проверить отдельно — либо ограничить набор
|
||
безопасными цветами, либо подстраивать яркость под тему.
|
||
|
||
---
|
||
|
||
## Что писать в макетах
|
||
|
||
В `sketches/` и `approved/` цвета стоят числами — **так и надо**, иначе макет
|
||
не будет выглядеть задуманным. Это не код.
|
||
|
||
Правило простое:
|
||
- **макеты** — числа, чтобы было видно замысел;
|
||
- **код** — имена из схемы, чтобы переключалось.
|
||
|
||
Проверка при реализации: **поиск по коду на цвета числами и на «#»**. Что нашлось —
|
||
то и надо заменить на схему. Исключение — цвета ассистентов из настроек
|
||
(см. выше) и, возможно, значения внутри самой схемы, где цвета как раз и задаются.
|
||
|
||
---
|
||
|
||
## Готовый образец у нас уже есть
|
||
|
||
В `ai/assistent`, файл `client-shared/.../ui/FolderTheme.kt` — тема описана
|
||
отдельным объектом, с именем, и в комментарии сказано: «Сейчас — одна тёмная тема;
|
||
в будущем — переключатель тем (светлая/тёмная)». Идею **берём**, детали —
|
||
|
||
**Чего в образце нет:** он соблюдается не везде. В том же клиенте **36 цветов
|
||
вписаны числами** прямо в экранах (`Color(0xFF4CAF50)` и подобные). Тема есть,
|
||
а половина цветов идёт мимо неё. Поэтому наш подход строже:
|
||
|
||
- **ни одного цвета числом вне самой схемы** — все цвета живут в одном месте;
|
||
- **именованные значения для смыслов** — тоже в теме, а не в экране;
|
||
- **проверяем на второй теме** — пока не переключили тему и не посмотрели, считать
|
||
готовым нельзя.
|
||
|
||
Разбор — `BORROW-FROM-ASSISTENT.md`, п. 3.10.
|
||
|
||
## Токены тёмной темы (на ней строится палитра)
|
||
|
||
Это **эталонный набор** — какие цвета и с какими именами есть в тёмной теме.
|
||
В макетах (`sketches/`, `approved/`) они стоят числами в `:root { --token: #... }`,
|
||
в коде приложения — через `MaterialTheme.colorScheme.*`. Значения **согласованы
|
||
с Android-клиентом** (`agentik-android/design/BORROW.md:39`), плюс расширения,
|
||
которых в десктопной основе не было.
|
||
|
||
| Токен | Назначение | Значение | Откуда |
|
||
|---|---|---|---|
|
||
| `--bg` | фон окна | `#121218` | основа |
|
||
| `--panel` | панели (шапки, боковая) | `#17212B` | основа |
|
||
| `--panel2` | «приподнятые» элементы на панели | `#1C2733` | Android |
|
||
| `--line` | разделители и рамки полей | `#232B36` | Android |
|
||
| `--fg` | основной текст | `#EBEBEB` | основа |
|
||
| `--dim` | приглушённый текст (время, подписи) | `#768C9E` | основа |
|
||
| `--accent` | главный акцент | `#6AB2F2` | основа |
|
||
| `--badge` | фон кружка непрочитанных | `#5EB5F7` | Android |
|
||
| `--err` | ошибки, опасные зоны, запись | `#EC3942` | основа |
|
||
| `--ok` | «на связи», успех проверки | `#63C88A` | Android |
|
||
| `--user-bubble` | пузырь сообщения пользователя | `#2B5278` | Android |
|
||
| `--bot-bubble` | пузырь сообщения ассистента | `#1C2733` | Android |
|
||
| `--a1`..`--a5` | **пользовательские** цвета агентов | `#6AB2F2` `#86C99A` `#C9A886` `#B79AE0` `#E28C8C` | Android |
|
||
|
||
**Важно про `--a1`..`--a5`:** это **не токены темы**. Они заданы для набора
|
||
по умолчанию и подобраны под тёмную тему. В коде это **пользовательские**
|
||
значения из настроек агента — кладутся в конфиг и читаются как `agent.color`,
|
||
а не через `MaterialTheme.colorScheme`. Иначе при смене темы агенты перестанут
|
||
отличаться друг от друга. Подробности — раздел «Особый случай» выше.
|
||
|
||
**Цвет текста на аксентном фоне:** на `--accent` (`#6AB2F2`) и `--badge`
|
||
(`#5EB5F7`) текст берётся **тёмным** (`#0F1922`), иначе не читается.
|
||
|
||
## Что осталось решить
|
||
|
||
- **Какие темы будут кроме тёмной.** Пока известно только: тёмная есть, светлая
|
||
предполагается.
|
||
- **Переключается ли тема в клиенте или берётся системная** (как в системе —
|
||
тёмная/светлая). От этого зависит, нужен ли в настройках отдельный переключатель.
|
||
- **Что делать с цветами ассистентов в светлой теме** (см. выше) — проверять
|
||
читаемость или ограничить набор.
|