Files
Luma/uikit_clear.md
T
wt e018be346a
Build Unsigned iOS ipa / Build Unsigned iOS IPA (push) Canceled after 0s
Build Unsigned macOS App / Build macOS ZIP (push) Canceled after 0s
iOS CI / Build and Test SwiftUI App (push) Canceled after 0s
added Docs/UIKIT.md uikit_clear.md tz.md tz_clear.md
2026-10-14 17:56:31 +07:00

48 KiB
Raw Blame History

Luma UI Kit — единый стандарт Web, Desktop и Android

Версия: 1.0. Дата: 14 октября 2026 года. Статус: целевой стандарт интерфейса.

Связанный документ: техническое задание.

Содержание

1. Назначение

UI Kit определяет визуальный язык, токены, компоненты, состояния и адаптацию Luma для Web, Desktop и Android. Документ применяется независимо от UI framework и не требует конкретной реализации нативных материалов, шрифтов или системных иконок.

Цель — узнаваемый продукт с одинаковой иерархией и понятным поведением на разных устройствах. Совпадение физического пикселя между ОС не требуется; соответствие ролям, пропорциям и состояниям обязательно.

Документ нормативный: значения токенов реализуются централизованно, компоненты показываются в отдельном каталоге состояний. Примеры токенов и размеров не обозначают уже написанную библиотеку.

2. Дизайн-принципы

UI-001. Контент и общение находятся на первом плане. Декор не конкурирует с текстом, avatar и основным действием.

UI-002. Основной accent — синий. Outgoing сообщения синие, incoming нейтральные. Направление различается также выравниванием, а состояние — иконкой/подписью.

UI-003. Элементы округлые, поверхности спокойные, navigation и forms следуют привычкам платформы. Нет обязательного копирования внешнего вида одной ОС на другую.

UI-004. Полупрозрачность поддерживает иерархию, но не ухудшает чтение. При отсутствии blur/пониженной прозрачности используется определённый opaque fallback.

UI-005. Состояния loading/empty/error/disabled/selected являются частью компонента, а не отдельной импровизацией каждого экрана.

UI-006. Жест ускоряет действие, но для значимого действия есть видимый/доступный альтернативный control.

UI-007. Пользовательские строки — русские, короткие и точные. «Отправлено», «Доставлено» и «Прочитано» не заменяют друг друга.

UI-008. Маленькое окно, клавиатура, увеличение текста и reduced motion поддерживаются системно, а не исправляются после завершения дизайна.

3. Единицы и токены

Величина Web Android Desktop
Layout unit u CSS px при стандартном масштабе dp Логическая единица UI, independent от device pixels
Размер текста rem/em с role mapping sp с font scale Системный scaling / logical font size
Border 1 CSS px или адаптированный hairline 1 dp по роли Логическая линия с корректным pixel snapping
Анимация ms ms ms
Цвет sRGB HEX + alpha Эквивалент sRGB Эквивалент sRGB

При изменении device pixel ratio компонент не должен физически уменьшаться. Растровые assets поставляются в нужных масштабах; logo и функциональные icons предпочтительно в vector.

3.1. Обязательные группы токенов

color.*, type.*, space.*, radius.*, size.*, border.*, shadow.*, motion.*, layer.*, breakpoint.*.

Каждый токен имеет light/dark значение или единое значение, назначение и допустимое применение. Локальная константа не заменяет существующий токен тем же смыслом.

4. Палитра

4.1. Semantic colors

Токен Light Dark Назначение
color.brand.accent #248FF5 #68B5FF Выбор, active icon, ссылка по проверенному контрасту
color.action.fill #0969C8 #0969C8 Filled primary button с белым текстом
color.action.onFill #FFFFFF #FFFFFF Текст primary action
color.text.primary #172B40 #F3F6FA Основной текст
color.text.secondary #526174 #B8C3CF Вторичный текст
color.text.muted #5E6C7E #A7B4C4 Метаданные при достаточном контрасте
color.surface.page #F4F7FA #101821 Фон приложения
color.surface.base #FFFFFF #18232F Основные панели
color.surface.raised #FFFFFF #213040 Dialog/card/popover
color.surface.incoming #E7ECF2 #293847 Incoming bubble
color.border.subtle #D7DFE8 #3C4B5D Divider/декоративная рамка
color.border.control #7A899A #8794A3 Значимая граница control
color.state.success #16713B #6DDA91 Успех/online/verified
color.state.successFill #16713B #16713B Filled accept/success control, белый текст
color.state.warning #8A4B00 #FFC46B Plaintext/предупреждение
color.state.error #B4232F #FF9199 Ошибка/destructive text
color.state.errorFill #B4232F #B4232F Destructive filled control
color.state.onErrorFill #FFFFFF #FFFFFF Текст destructive filled control
color.focus.ring #0969C8 #8BC6FF Keyboard focus
color.overlay.scrim #000000 / 0.52 #000000 / 0.64 Модальная подложка

Brand accent используется как цвет бренда; это не разрешение печатать мелкий белый текст на любой голубой поверхности. Filled actions используют action.fill. Для ссылок на светлом фоне применяется достаточно тёмный action.fill либо другой проверенный role token.

4.2. Сообщения и градиенты

Токен Значение Назначение
gradient.message.outgoing #0969C8 → #0874BA Outgoing text/audio/file bubble
color.message.onOutgoing #FFFFFF Основной текст outgoing
color.message.outgoingMetadata Основной secondary вне bubble Дата/status за пределами синей поверхности
gradient.brand.hero #1461C7 → #1F9EF5 → #70D6F5 Login/lock background, декоративная область
gradient.media.video #0F2B4A → #176EA3 Video placeholder
gradient.media.videoNote #144D8F → #12A3D4 VideoNote placeholder
gradient.call #1C2B3D → #000000 Call scene

Направление градиентов — от верхнего левого угла к нижнему правому. Для текстовых bubbles используется тёмный сине-голубой градиент, чтобы белый body оставался читаемым; более яркий hero gradient остаётся декоративным.

Для обычного белого текста расчётный контраст с концами outgoing gradient — около 5.43:1 и 4.98:1. Контраст промежуточных цветов и всех фактических состояний проверяется при реализации. Полупрозрачный secondary text внутри bubble не должен снижать контраст ниже целевого порога.

4.3. Аватары и имена участников

Fallback avatar получает стабильный цвет по нормализованной identity. Цвет не меняется при rerender/перезапуске. Palette должна обеспечивать читаемый белый или тёмный foreground; случайный hue не используется без выбора контрастного текста.

Имя автора MUC может иметь устойчивый цвет, но не является единственным признаком identity. Имя остаётся читаемым в обеих темах. Цвет для имени и фон аватара могут отличаться по насыщенности.

4.4. Запрещённые применения

  • Новый близкий синий для той же роли без добавления token.
  • Белая мелкая подпись на ярком accent без проверки контраста.
  • Ошибка/online/selected, различимые только цветом.
  • Hardcoded light background с унаследованным dark foreground из другой темы.
  • Прозрачный control без определённого фона/границы/focus state.

5. Типографика

Используется системный sans-serif шрифт платформы. Единая роль важнее одинакового имени font family. Fallback поддерживает кириллицу, emoji и символы JID. Mono нужен для fingerprint, не для всего интерфейса.

Токен Размер / line height Weight Применение
type.brand 42 / 50 700 Название на login
type.hero 30 / 38 600 Имя звонящего
type.title 22 / 28 700 Крупный заголовок формы/dialog
type.heading 17 / 24 600 Имя списка, toolbar title
type.body 16 / 24 400 Сообщение, поле, основной текст
type.bodyStrong 16 / 24 600 Выделенный текст/primary label
type.subbody 14 / 20 400 Preview списка, вторичные поля
type.caption 12 / 16 400/500 Метаданные, пояснения
type.badge 12 / 16 700 Unread/count
type.mono 12 / 18 400 Fingerprint/техническое значение

Размеры масштабируются пользовательскими настройками; фиксированная высота row не должна обрезать увеличенный текст. Desktop compact density может уменьшать вторичный текст до 13/18, но основной message body не становится мелкой служебной подписью.

Таймеры/duration используют tabular numerals. Link/упоминания различимы, доступны клавиатуре и не ломают line wrapping.

5.1. Ограничение строк

  • Имя и preview списка: 1 строка при обычном масштабе; при большом тексте допустим адаптивный рост.
  • Имя звонящего: до 2 строк.
  • Toast: до 2 строк, дальнейшее сообщение — dialog/inline error.
  • Compact reply: 1 строка и ellipsis.
  • Message body: без произвольного line clamp; длинный контент может иметь доступное «Показать полностью» только при отдельном согласованном лимите.
  • JID/filename/fingerprint: безопасный wrap/ellipsis с возможностью прочитать/скопировать полное значение.

6. Отступы, размеры и формы

6.1. Spacing scale

Токен u
space.1 4
space.2 8
space.3 12
space.4 16
space.5 20
space.6 24
space.7 32
space.8 40
space.9 48

Компонентные исключения допустимы для оптического выравнивания: bubble padding 13×9, input 14/12/9, metadata gap 4. Они именуются внутри компонента, не создают бессистемный глобальный scale.

6.2. Радиусы

Токен u Применение
radius.small 6 Reply thumbnail
radius.control 12 Компактная карточка/системный fallback
radius.field 16 Caption field
radius.reply 17 Compact reply
radius.media 20 Photo/video island
radius.composer 21 Поле composer
radius.dialog 28 Auth/dialog card
radius.pill Половина высоты Badge/chip/toast
radius.circle 50% Avatar/round control

Message bubble имеет отдельную directional geometry: основное скругление 20, нижняя асимметрия/небольшой хвост на стороне отправителя с выступом около 4 u. Он не должен уменьшать внутреннюю область текста. Vector/path реализации обеих направлений являются зеркальными вариантами одного компонента.

Фото/видео не получают текстовый хвостик: у них самостоятельная островковая рамка.

6.3. Контролы

Роль Visual size Hit area
Composer send/attach/record 42×42 Touch min 48×48; pointer min 44×44
Audio play 44×44 Touch min 48×48
Standard icon button 24 icon в 40/44 visual Touch min 48×48
Primary form action Height min 48 Вся кнопка
Call control 58×58 circle Не меньше visual size
Unread badge min height 22 Не отдельная обязательная target
Input min height 44, composer visual min 42 Не обрезается при scale

Увеличение hit area не должно перекрывать target соседней кнопки. При узкой ширине gap и общий layout перераспределяются.

7. Поверхности, границы и elevation

Уровень Поверхность Применение
Page page Фон, timeline
Base base Sidebar, forms, основной контент
Raised raised + border/elevation Popover, dialog, floating panel
Glass Полупрозрачная base surface + blur Search/composer/toolbars
Inverse Тёмная сцена + контрастный текст Media viewer/call

Glass light fallback: base opaque. Glass dark fallback: base opaque. При blur фон имеет достаточно непрозрачный слой для текста; blur не единственный источник читаемости. Reduced transparency отключает blur и сохраняет border.

Shadows:

  • shadow.floating: black alpha 0.14, blur 24, offsetY 12 в light; более мягкий/ограниченный вариант в dark;
  • shadow.toast: black alpha 0.18, blur 12, offsetY 4;
  • shadow.callPreview: black alpha 0.38, blur 16, offsetY 8.

List row не получает отдельную тяжёлую тень. Border subtle декоративный; значимые focus/control boundaries используют более контрастный role token.

8. Адаптивная компоновка

8.1. Breakpoints

Это продуктовые диапазоны доступной ширины, а не определение типа устройства.

Диапазон Ширина Layout
Compact <720 u Одна основная панель, переход список → чат
Medium 720…1099 u Sidebar + detail при достаточной полезной ширине
Wide ≥1100 u Sidebar + detail, расширенная зона контента

В medium split включается только если после sidebar остаётся минимум 400 u для detail; иначе compact. Приложение работает при viewport 320 u через reflow; специальные фиксированные размеры уменьшаются до доступной ширины.

8.2. Sidebar и detail

Sidebar min 240, preferred 290, max 380. Default desktop window ориентир 1080×720, рекомендуемый minimum 840×560; при фактически меньшем окне допускается compact layout, а не обрезанный недоступный контент.

Detail растёт с окном. Максимальная читаемая ширина обычного text bubble — 640 u и не более 78% доступной message row. Очень короткий текст не растягивается до максимума. Timeline может иметь центрированный content column с max 1000 u.

8.3. Platform shell

Платформа/режим Navigation
Android compact Нижняя навигация: Контакты / Звонки / Чаты / Настройки
Mobile Web Аналогичная compact bottom navigation, с учётом browser safe areas
Desktop/Web wide Sidebar navigation/list + выбранный detail
Android large screen Adaptive split/rail по доступной ширине

Внутри compact чата нижняя глобальная навигация скрыта, Back возвращает к списку. Search остаётся сверху соответствующего списка. Keyboard/IME не перекрывает composer; изменение viewport не сбрасывает draft.

9. Иконки

Единый набор outline/filled vector icons выбирается для каждой платформы с согласованной семантикой. Использование конкретного proprietary symbol set не требуется. Толщина, оптический размер и baseline согласованы в каталоге.

Роль Графическая семантика
Контакты Человек/контакты
Звонки Телефон
Чаты Два сообщения
Настройки Шестерёнка
Новый чат Карандаш/новое сообщение
Новая группа Несколько людей
Поиск/очистить Лупа/крестик в круге
Вложения Плюс
Отправить Стрелка вверх
Ответить/переслать Стрелка влево/вправо с поворотом
OMEMO/plaintext Закрытый/открытый замок
Decryption error Щит с предупреждением
Retry Круговая стрелка
Сохранить Стрелка вниз/скачивание
Завершить звонок Опущенная трубка
Turn camera Камера с круговыми стрелками

Обычный icon size 20/24 u; metadata 12/14. Иконка без текста имеет accessible name и tooltip на pointer, если смысл не очевиден. Emoji не заменяет функциональную пиктограмму кнопки.

10. Компонент Avatar

UI-AVATAR. Circle, photo fill с crop, fallback — initials/group icon и стабильный фон. Не смешивать photo fit с avatar fill: фотографии сообщений не обрезаются как avatar.

Вариант Размер
List 50×50
Profile 64×64
Call hero 132×132
Compact inline 32×32 при необходимом контексте

Initials около 35% diameter, semibold; group icon около 31%. Status dot bottom-end, diameter 25% avatar, border 2.5 u цветом окружающей поверхности. Direct dot означает online, group — joined. Accessible label включает имя и статус. Offline не рисуется ложным зелёным dot.

Состояния: photo, fallback, loading cached image, online/joined, offline, image error. Broken image не создаёт пустой невидимый avatar.

11. Компонент ConversationRow

Композиция: avatar → текстовая колонка → trailing time/unread. Gap avatar/text 12. Внешние insets horizontal 12, vertical 8; высота определяется содержимым, ориентир 72 u.

  • Имя — heading.
  • Preview — subbody secondary.
  • Время — caption secondary.
  • Межстрочный gap 4/5.
  • Иконка group/encryption рядом с preview, не вместо имени.
  • Badge count >0, white on action.fill, padding 7×3, min width 22.
  • В основном списке значение выше 99 показывается «99+»; accessible name сообщает фактическое число.
  • Multiaccount подпись — caption secondary, только когда нужно различать контекст.

Состояния: default, hover на pointer, pressed, keyboard focus, selected wide-panel, unread, online, muted при наличии функции, loading/empty отдельно от row.

Selected row: accent-tinted surface и ненавязчивый маркер/фон; hover слабее selected. Focus ring не исчезает на selected. Baseline focus outline 2 u с offset 2 u; при недостаточном контрасте используется двойная граница/контрастный separating layer.

12. SearchField

Поле располагается над фильтруемым списком. Height min 40 visual/48 touch target, radius pill либо control по platform shell. Horizontal inset 12, vertical 8, icon/text gap 8, outer margin 12.

Leading search icon, placeholder «Поиск чатов»/«Поиск контактов»/«Поиск звонков». Clear button появляется при непустом запросе. Native input behaviors сохраняются: selection, keyboard focus, paste и Escape очистки/закрытия по контексту.

Состояния: empty, filled, focused, disabled только при реальной невозможности, no results через отдельный empty state. Search field не обещает поиск message body, если реализована фильтрация списка.

13. MessageRow и Bubble

UI-MESSAGE. Incoming слева, outgoing справа. Outer horizontal inset 12, row gap 8. Opposite minimum space 54 для текста и 16 для media, с уменьшением в узком viewport. Body wrapping не расширяет страницу горизонтально.

Message stack:

  1. optional group sender name;
  2. optional compact source reply;
  3. body/media;
  4. reaction chips;
  5. metadata.

13.1. Body

Text/file padding horizontal 13, vertical 9. Audio/voice — 13×10. Outgoing gradient + white; incoming neutral surface + primary. Body type.body.

Plaintext/decryption warning расположен в metadata и доступен screen reader. Не добавлять замок каждому слову или watermark поверх читаемого текста.

Text bubble использует общую directional rounded shape; media островок имеет независимый radius 20. Long URL/word безопасно переносится; copy возвращает исходный текст, а не строку с декоративными разрывами.

13.2. Metadata

Caption, gap 4, horizontal inset 4, вне основного colored body. Время hour:minute, marker «изм.», security warning и outgoing status.

Состояние Icon/подпись
Sending Часы / «Отправка…»
Sent Галочка / «Отправлено»
Delivered Отличимая delivery-галочка / «Доставлено»
Read Заполненный/двойной read marker / «Прочитано»
Failed Warning red / «Не отправлено», доступен retry по ТЗ

На compact можно оставить icon и доступный подробный label, на focus/hover показывать расшифровку. Статусы не различаются только tint.

13.3. Tombstone

Иконка удаления + «Сообщение удалено», subdued text/italic по доступности. Положение исходного сообщения сохраняется, прежние media/reaction/reply content не видны. Tombstone не приглашает к запрещённым edit/forward.

13.4. Selection и context menu

Touch: long press открывает actions; pointer: context click/явное menu; keyboard: доступная menu action. В selection mode видны checkmarks/count и панель массовых действий. Swipe reply отключён.

Список actions определяется ТЗ. Недоступное действие скрывается либо disabled с причиной, но не выполняет частично другую операцию под тем же названием.

14. CompactReply и ThreadFocus

Compact source bubble: max width 230, min height 34, radius 17, vertical padding 7, horizontal 10…12. Text subbody medium, one line, optional thumbnail 27×27/radius 6. Тонкий border 1.25 u; фон приглушённый.

Отступ/дуга отражают направление исходного сообщения. Curve width 58/height 34, stroke 2.4 round caps, horizontal offset около 18. Нельзя снижать opacity всего текста ниже readable contrast; muted effect достигается background/border, а не нечитаемой надписью.

При известном target компонент interactive и имеет label «Открыть ветку ответа». При preview без target он статичен и не показывает ложный hover-link.

ThreadFocus: затемнённый/raised отдельный слой, источник, число ответов, хронологическая ветка, selected reply metadata. Есть Close/Escape/Back и корректный focus restore. Bracket декоративный, не отдельный target. Это фокус replies в существующем чате.

15. ReactionChip и EmojiPicker

Chip: emoji + count, gap 3/4, padding 8×4, pill. Strip gap 5/8, wrap в узкой row.

Вариант Представление
Чужие реакции Neutral subtle background + readable border
Есть own reaction Accent-tinted background + accent border + accessible own state
Hover/focus Нативная/общая interactive обратная связь
Pending mutation Ненавязчивый progress, без ложного подтверждения failure

Quick reactions: 👍 ❤️ 😂 😮 😢 🔥. Полный picker: header «Выберите эмодзи», Close/«Готово», grid, category navigation. Emoji visual 28, cell 46×46 с touch hit area минимум 48. Grid адаптивный; focused item виден и управляется keyboard.

Text search в emoji picker не обязателен. Если добавлен, он следует общему SearchField и не меняет базовую семантику reactions.

16. Composer

Horizontal structure: attach → multiline input → send/record. Gap 8. Outer horizontal 10/12, top 6/8, bottom 8 плюс safe area. Control visuals 42×42, hit targets по разделу размеров.

Input: min height 42 visual, radius 21, leading 14/trailing 12/vertical 9. Body font, от 1 до 6 строк до внутренней прокрутки. Placeholder «Сообщение»; edit mode «Изменить сообщение». Emoji control справа input, secondary, icon 20.

  • Непустой draft: send arrow accent/action.
  • Пустой draft: record action с доступным выбором audio/video.
  • Reply/edit banner: над input body, автор/preview и Cancel.
  • Upload preparation: progress и доступный cancel, текст не теряется.
  • Recording: elapsed, waveform/indicator, cancel, finish/lock.
  • Selection: separate action bar, обычная отправка не конфликтует с массовыми actions.

Keyboard contract Web/Desktop: Enter отправляет при настройке «Enter для отправки», Shift+Enter — новая строка; можно переключить поведение. IME composition не отправляет сообщение по промежуточному Enter. Esc закрывает локальный popup/отменяет reply/edit с сохранением исходного draft по сценарию.

Touch recording gestures не являются единственным способом: есть доступные «Начать», «Остановить», «Отменить». Back во время capture спрашивает о потере записи либо явно отменяет по утверждённому сценарию.

17. MediaIsland и viewer

17.1. Фото/видео

Default width 268, max available width минус row insets. Radius 20, border 1, thumbnail inset 6. Photo natural height по ratio, baseline clamp 164…328, с proportional уменьшением на узком экране. Object-fit/scale mode — contain.

Filename/size badge снизу: caption, white on достаточно тёмной scrim, padding 8×5, pill; inset 9. Expand icon сверху справа с hit area. Video имеет центральный play и duration.

Состояния: placeholder, loading, thumbnail, ready, playing для inline применимого типа, failed/retry. Error не замещается бесконечным spinner.

17.2. Audio/voice

Content default width 252 с clamp доступной ширины. Play circle 44, waveform около 30 high, progress/seek, duration и speed chip. Voice speed 1×/1.5×/2×; audio filename visible.

Seek имеет keyboard arrows/accessible slider semantics и touch target выше визуальной линии. Loading, paused, playing, ended и failed различимы.

17.3. VideoNote

Circle 144 idle, 176 playing при достаточном месте; при узком viewport размер уменьшается. Play icon 24, duration pill снизу, border 1. Увеличение не должно резко двигать viewport или перекрывать соседние controls.

17.4. Fullscreen viewer

Root overlay, тёмный фон, zoom/pan для фото, controls для видео. Обязательно доступны Close button, Escape на keyboard и Back на Android; vertical dismiss — дополнительный touch gesture. Close target располагается в safe area и не закрывает важное media.

Zoomed photo pan не запускает dismiss. После закрытия focus возвращается к исходному элементу, viewport остаётся на том же сообщении. Download/save — отдельное явное действие.

18. AttachmentPreview

Modal/panel с title «Перед отправкой», grid, подписью и action row. Grid cell min 128/max 190, column gap 18/20, row gap 22/24, container padding 16. В compact grid адаптируется до одной/двух колонок.

Caption field radius 16/padding 13×10, 1…4 строки. Нижняя panel raised/glass с opaque fallback, padding 14/16. Summary слева, primary send справа; mobile может переносить action row без обрезки.

На sending отмена/закрытие имеют определённую доступность; failed items остаются с clear status и retry. Caption не показывается как доставленная, если её отдельная отправка завершилась ошибкой.

19. LocationPicker

Header «Отправить геопозицию», карта/marker, текущая выбранная точка, «Моя геопозиция» и primary «Отправить». При denied permission — inline explanation и ручной выбор.

Map не поглощает все keyboard/Back actions. Выбор координат доступен через альтернативный ввод, если map недоступна. Preview location message — компактная карта/иконка и координаты/label; tap открывает просмотр без автоматического фонового tracking.

20. CallScene и CallHistoryCard

CallScene — inverse fullscreen/large overlay. Remote video занимает доступный фон, контрастная scrim защищает labels. Local video 118×168/radius 22, top-end с safe area; на compact масштабируется и не перекрывает controls.

Без video: call gradient, avatar 132, name hero до 2 строк, media type subbody, status/duration tabular. Основные controls снизу, visual circles 58 и подписанные labels.

  • Incoming: decline red и accept green/dark-success fill с readable white text.
  • Connecting: status и доступный cancel.
  • Connected: mute, audio route при поддержке, camera/switch при наличии, hangup red.
  • Permission/error: понятное пояснение и возврат без скрытой активной записи.

Control selected state передаётся icon + label/accessible state, а не только прозрачностью. Caption labels имеют достаточный контраст на scrim.

HistoryCard: max width 300, icon circle 42, content gap 12, title bodyStrong/subbodyStrong, subtitle caption, padding 14×10. Outcome icon/text: completed success, missed/failed/declined error, cancelled/answeredElsewhere neutral. Направление определяется также arrow/текстом.

21. Auth, Settings, Encryption и Lock

21.1. AuthCard

Hero gradient background; centered column max 460, outer horizontal 24/vertical 48, адаптация к keyboard. Logo tile 88/radius 26, brand 42, card radius 28/padding 24…28.

Form: JID, password с show/hide, advanced connection options, primary «Войти». Loading «Подключение…» и spinner. Error у поля/общая область без потери ввода. Native host/port и Web WSS endpoint представлены соответствующими полями, а не общим неработающим transport selector.

21.2. Settings

Grouped sections, стандартные switches/list rows/links. Profile avatar 64. Основные sections: аккаунты, профиль, соединение, шифрование, уведомления, блокировка, приватность.

Long values читаются/копируются; destructive logout отделён от обычных preferences. Multiaccount selection имеет checkmark и account identity.

21.3. EncryptionPanel

Итоговый режим чата, global/override control, список устройств, protocol badge, fingerprint mono, trust. Verified/trusted/undecided/compromised различаются текстом и символом. «Готово» не означает автоматической verification.

Fingerprint selectable/copyable, разбит на читаемые группы; label устройства не заменяет fingerprint. Empty devices объясняет следующий шаг, не показывает фиктивный secure success.

21.4. LockScreen

Hero/нейтральный фон и полностью скрытое sensitive content. Card radius 28, lock icon 44, title 22, field/action max 260 при обычной ширине, spacing около 22/24. Passcode input masked, explicit unlock, error inline и biometric action только при реальной доступности.

Lock не имитируется прозрачным blur поверх читаемого чата. Не существует автоматически перенесённой native-biometric кнопки в неподдержанном браузере.

22. Feedback, dialogs и слои

Компонент Контракт
Toast Краткий результат, max 2 строки, закрываемый/доступный screen reader
Inline error Ошибка поля/операции рядом с источником
Alert/dialog Важная ошибка/подтверждение с ясными действиями
Loading Spinner/progress + конкретная операция
Empty state Название, пояснение, доступное next action
Connection status Компактный читаемый статус в заголовке/панели

Toast: padding 16×10, gap 8, pill, raised/glass fallback, shadow.toast. Default display 2.5 с; при accessibility/длинном тексте длительность увеличивается или доступно persistent alternative. Toast не единственное место критической ошибки.

Layers:

Токен Значение
layer.base 0
layer.sticky 10
layer.popover 40
layer.dialog 80
layer.media 100
layer.call 200
layer.toast 300
layer.lock 400

Это роли stacking, не обязательные literal z-index в каждой технологии. При открытии слоя проверяются активные dialogs: неподходящий старый modal закрывается/уступает по сценарию. App lock имеет приоритет sensitive content. Error dialog при lock не раскрывает текст переписки.

Modal traps focus, имеет label и close action. После close focus восстанавливается. Browser/Android Back сначала закрывает верхний modal, затем navigates.

23. Анимации и жесты

Токен/эффект Значение
motion.fast 120 ms
motion.base 180…220 ms
motion.panel 240…300 ms
Timeline entrance До12 rows, stagger 35 ms, rise 16, scale 0.94
Outgoing append Spring около 440 ms; start scale 0.2/rise 12 при допустимом layout
Incoming append Start scale 0.4/rise 10
VideoNote resize Spring около 320 ms
Reply swipe return Spring около 240 ms

Burst >4 appended rows/архив не анимируется как несколько свежих сообщений. Recycled rows не играют entrance повторно при каждом scroll.

Reduced motion: убрать scale/slide/stagger, оставить короткое fade или мгновенную смену. Важное состояние не зависит от завершения анимации. Animation cancellation не оставляет invisible interactive control.

Touch reply: horizontal activation 24, trigger 64, max offset 76; раннее доминирование горизонтали 1.6, после lock 1.05. Вертикальный scroll приоритетен. Haptic при пороге там, где поддержан и разрешён.

Record: hold около 240 ms, cancel left 92, lock up 78; размеры адаптируются к ограниченному пространству, доступные кнопки остаются.

Viewer swipe: vertical dominance 1.15, distance около 14% height clamp 88…140; fast predicted endpoint может завершать жест. На pointer Close/Escape остаются основным способом.

24. Accessibility и ввод

UI-A11Y-001. Целевой контраст обычного текста минимум 4.5:1, крупного 3:1; значимых controls/focus минимум 3:1 относительно соседних поверхностей. Проверяются фактические composite colors, не только исходные HEX.

UI-A11Y-002. Все действия доступны screen reader и имеют names/states. Icon-only button не называется именем файла icon.

UI-A11Y-003. Web/Desktop полностью поддерживают Tab/Shift+Tab, Enter/Space для действий, Escape для закрытия и предсказуемый focus order. Hover-only actions доступны также по focus/tap.

UI-A11Y-004. При text scale/zoom до 200% интерфейс reflow без потери основных действий. Fingerprint/URI можно прочитать полностью; text body не скрывается за fixed height.

UI-A11Y-005. Touch targets минимум 48×48 u для действий; визуально меньшая icon сохраняет просторный hit region. На pointer target не меньше 44×44 для основных icon actions.

UI-A11Y-006. Errors связаны с input, loading не бесконечно повторяется screen reader, live messages объявляются умеренно и не перехватывают focus.

UI-A11Y-007. Reduced motion/transparency и high contrast имеют определённые варианты. Цвет не единственный способ различения unread/failed/verified.

UI-A11Y-008. Record/call/media controls отражают фактическую активность camera/microphone. Для destructive есть явное подтверждение области действия.

25. Каталог состояний и приёмка UI

Поставляемая библиотека компонентов имеет отдельный доступный каталог/preview, не требующий реального XMPP login.

Обязательные fixtures:

  • light/dark и reduced motion/transparency;
  • compact 320/390, medium 840, wide 1280/1440;
  • обычный и 200% текст;
  • короткие/длинные имена/JID/URL/filename;
  • чат без сообщений, search без результатов, offline и syncing;
  • все delivery/security states;
  • incoming/outgoing/group/reply/tombstone/reactions;
  • media loading/ready/error и partial batch;
  • recording start/locked/finalizing/error;
  • incoming/connecting/active/failed call;
  • keyboard focus, selection и menus;
  • lock, denied permissions и уведомления без preview.

25.1. Чек-лист

  • Все цвета/шрифты/spacing берутся из токенов по роли.
  • Navigation соответствует ширине и платформе.
  • Любая важная action доступна без жеста/hover.
  • Focus не теряется в modal/viewer и возвращается после close.
  • Long content и text scale не ломают layout.
  • Incoming/outgoing/delivery/security определяются без одной лишь окраски.
  • Media не обрезается неожиданно и не растягивается.
  • Keyboard/IME не отправляет незавершённый ввод.
  • Loading/ошибка/cancel завершаются корректным состоянием.
  • Contrast проверен для фактических цветов и прозрачностей.
  • Motion/transparency preferences работают.
  • UI соответствует functional predicates tz_clear.md.

26. Развитие стандарта

Новый компонент сначала определяется как набор ролей/состояний, затем добавляется в tokens/catalog и после этого используется в экранах. Новый вариант существующего компонента получает имя и назначение; нельзя создавать похожую локальную копию с немного другим цветом/radius без причины.

Изменение токена проверяется на всех затронутых компонентах, light/dark и платформах. Несовместимые изменения версии UI Kit документируются и мигрируются согласованно.

Стандарт сохраняет общий характер Luma, при этом concrete native widget и способ реализации blur/vector/animation выбираются платформой. Ни одна из библиотек Web/Desktop/Android не считается реализованной только по существованию этого документа.