Files
subochev 27f349550c Макеты — один sketches/index.html; approved/ удалён
- sketches/index.html: все экраны одним документом в порядке 1·… (14–19 — бывшие approved)
- approved/ (4 файла групп + 3 макета + README) удалён как дубль
- стили вынесены в sketches/style.css
- README, THEMES, BORROW-FROM-ASSISTENT, MARKDOWN-SOURCE, MIC-ASR-SEARCH
  приведены к фактическому состоянию
2026-09-28 10:07:57 +03:00

175 lines
11 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.
# Цветовые темы: цвета не пишем в коде
**Правило:** в коде **не должно быть цветов числами**. Цвет берётся из текущей
цветовой схемы по смыслу. Тем будет **несколько** (тёмная, светлая и другие),
и одна и та же деталь интерфейса должна выглядеть правильно в каждой.
**Почему так:** если цвет вписан числом, при смене темы он останется прежним —
и на светлом фоне окажется тёмно-серый текст, тёмная тень или невидимая граница.
Такие места обычно находят уже у пользователя.
---
## Как это выглядит в коде
### Неправильно
```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`), иначе не читается.
## Что осталось решить
- **Какие темы будут кроме тёмной.** Пока известно только: тёмная есть, светлая
предполагается.
- **Переключается ли тема в клиенте или берётся системная** (как в системе —
тёмная/светлая). От этого зависит, нужен ли в настройках отдельный переключатель.
- **Что делать с цветами ассистентов в светлой теме** (см. выше) — проверять
читаемость или ограничить набор.