Дизайн-система · v1 · 2026

Монохром.
Острова. Один синий.

Набор токенов, компонентов и правил для мобильных и веб-продуктов. Один источник — tokens.json — и из него CSS и Compose Multiplatform для Android, iOS и Desktop.

30компонентов
43цветовых токена × 2 темы
27стилей текста
169иконок Lucide
01

Принципы

Экран собирается как хороший документ: белый лист, серые острова, чёрное главное действие и один синий акцент.

Монохром + один синий

Главное действие — чёрная капсула primary. Синий accent — фокус, выбор, оплата. Остальное — белый, серый, чёрный.

Острова, а не панели

Навигация плавает отдельными капсулами над контентом. Контент — плоские серые Island на белом фоне.

Зона большого пальца

Главная кнопка внизу, во всю ширину, 56 px. Цель касания — не меньше 48 px.

Контраст проверен тестом

Пары текст/фон проходят WCAG AA в обеих темах — это проверяет автотест, а не глаз.

02

Цвет

43 семантических токена. Каждый задан для светлой и тёмной темы — переключите тему наверху, образцы перекрасятся. Значения: светлая · тёмная.

bg
#FFFFFF · #000000
Фон экрана (как лист документа). На нём текст ink, ink-2, accent-text.
surface
#F5F5F7 · #1D1D1F
Острова и карточки — серая подложка, как острова в документах. Весь текст читается.
surface-2
#E8E8ED · #2C2C2E
Утопленные зоны и вторичные кнопки: сегмент, чип, круглая кнопка, скелетон. Текст на нём только ink (не ink-2).
elevated
#FFFFFF · #1D1D1F
Поднятая поверхность над scrim: нижний лист, диалог. В тёмной теме светлее bg, иначе лист сливается с затемнением.
elevated-fill
#F5F5F7 · #2C2C2E
Круг иконки и заливки внутри elevated (в тёмной теме surface совпал бы с листом).
glass
#FFFFFFB8 · #1D1D1FB8
Стеклянный остров (таб-бар, тулбар) поверх контента, всегда вместе с blur-*.
line
#D2D2D7 · #38383A
Линии таблиц, разделители строк — декоративные.
line-strong
#86868B · #7C7C80
Рамка поля, outline-кнопки, свитча: 3:1 на bg и surface в обеих темах.
ink
#1D1D1F · #F5F5F7
Основной текст и иконки на любой поверхности.
ink-2
#6E6E73 · #86868B
Второстепенный текст, подписи, плейсхолдер на bg и surface. На surface-2 не ставить.
ink-3
#86868B · #6E6E73
Только disabled-текст и декоративные иконки. Для обычного текста не использовать.
accent
#0071E3 · #2997FF
Синий — единственный цвет. Номера разделов, включённый свитч, прогресс, фокус — без текста поверх. Под текст — accent-fill. Как текст — только на bg; иначе accent-text.
accent-fill
#0071E3 · #0071E3
Заливка с текстом: акцентная кнопка, акцентный лид строки, отмеченный чекбокс. В обеих темах одна — белый текст читается (≥ 4,5:1); светлый accent тёмной темы под текст не годится.
accent-pressed
#0058B0 · #0058B0
Нажатое состояние accent-fill.
on-accent
#FFFFFF · #FFFFFF
Текст и иконки на accent-fill и accent-pressed — белый в обеих темах.
accent-soft
#EAF3FE · #0B2A4A
Выделенный остров (важная оговорка), информационный алерт.
accent-ink
#0058B0 · #8EC5FF
Текст на accent-soft.
accent-text
#0066CC · #2997FF
Ссылки и ghost-кнопки на любой поверхности (bg, surface, surface-2).
danger
#C42121 · #FF6B6B
Ошибка: текст ошибки, рамка поля с ошибкой, деструктивная кнопка. Всегда с иконкой или словом.
danger-soft
#FBE9E9 · #3A1416
Фон алерта и тоста ошибки.
danger-ink
#841717 · #FFA3A3
Текст на danger-soft.
success
#12823B · #4CC97A
Успех: иконка, индикатор, знак «+» у сумм. Всегда с иконкой или словом.
success-soft
#E8F6ED · #0F2C1A
Фон алерта успеха.
success-ink
#0D622C · #8EE0AB
Текст на success-soft.
warning
#C97400 · #FFB249
Предупреждение: только иконка или полоса, не текст. ≥3:1 на bg, surface, warning-soft.
warning-soft
#FFF5E8 · #33220A
Фон алерта предупреждения.
warning-ink
#7A4A0C · #FFD08A
Текст на warning-soft.
info-soft
{accent-soft} · {accent-soft}
Информационный алерт = выделенный остров accent-soft (отдельного синего нет, чтобы не спорить с акцентом).
info-ink
{accent-ink} · {accent-ink}
Текст информационного алерта.
knob
#FFFFFF · #F5F5F7
Бегунок свитча: всегда светлый, в обеих темах.
disabled-bg
#E8E8ED · #2C2C2E
Заливка неактивной кнопки и поля.
disabled-ink
#AEAEB2 · #636366
Текст неактивного контрола (WCAG не требует контраста для disabled).
scrim
#00000066 · #000000A3
Затемнение под листом и диалогом.
primary
{ink} · {ink}
Главная кнопка (CTA): чёрная капсула в светлой теме, светлая в тёмной — как тёмный CTA-остров документа.
primary-pressed
#424245 · #D2D2D7
Нажатое состояние primary.
on-primary
{bg} · {bg}
Текст и иконки на primary и primary-pressed.
inverse
#1D1D1F · #F5F5F7
Тост и выбранный чип: инверсия темы.
on-inverse
#F5F5F7 · #1D1D1F
Текст на inverse.
hero
#000000 · #1D1D1F
Чёрная обложка-герой (как обложка документа). В тёмной теме приподнята до #1D1D1F, чтобы не слиться с фоном.
hero-2
#1D1D1F · #2C2C2E
Карточки-факты на hero.
hero-ink
#F5F5F7 · #F5F5F7
Заголовок и цифры на hero и hero-2.
hero-ink-2
#A1A1A6 · #98989D
Подзаголовок и подписи на hero и hero-2 (≥4,8:1).
hero-line
#424245 · #48484A
Обводка капсулы-метки на hero, декоративная.
03

Текст

Системный шрифт платформы: San Francisco на Apple, Roboto на Android, системный на вебе. Файлы шрифтов не поставляются — нечего лицензировать. Цифры — моноширинные.

12 480,00 сом
display · 36px/40px · 800
Крупные суммы и цифры-герои. Один на экран.
Главная
h0 · 32px/40px · 700
Крупный заголовок страницы-вкладки в тулбаре.
Подтвердите номер
h1 · 24px/32px · 700
Заголовок экрана, листа, пустого состояния.
Удалить черновик?
h2 · 22px/28px · 700
Заголовок документа и модального диалога.
Последние операции
h3 · 18px/24px · 500
Заголовок секции и вложенный заголовок тулбара (по центру).
Нет сети
title · 18px/24px · 600
Заголовок острова, CTA-острова, пустого состояния.
Октябрь 2026
headline · 17px/24px · 600
Заголовок вложенного тулбара, месяца в календаре, итог чека.
Код отправлен на +992 92 *** 45 67
body-l · 16px/24px · 400
Основной текст.
Наличные
body-l-med · 16px/24px · 500
Значение поля, акцент в строке.
Данные обновляются раз в 5 минут.
body-m · 15px/22px · 400
Текст острова, алерта, диалога, ячейки таблицы.
Задача выполнена
body-m-med · 15px/22px · 500
Тост, значение в реквизитах, сумма в строке.
Сегодня, 14:32
body-s · 14px/20px · 400
Вторичный текст, подпись и подсказка поля.
Скопировано
body-s-med · 14px/20px · 500
Текст алерта, тоста, кнопки S, чипа.
PDF · 2 страницы
caption-m · 13px/18px · 400
Подсказка поля, подстрока строки списка, время в пуше.
Готово
caption-m-med · 13px/18px · 500
Метка-капсула (Tag), режим камеры.
Задачи
caption-l · 12px/14px · 400
Подписи таб-бара, мелкие метки.
NEW
caption-s · 10px/12px · 400
Бейджи, сноски. Минимум, мельче не бывает.
Продолжить
button-l · 17px/20px · 600
Кнопка L 56: главное действие (CTA).
Отмена
button-m · 16px/20px · 500
Кнопка M 48: вторичные действия.
Изменить
button-s · 14px/20px · 500
Кнопка S 36: в строках и таблицах.
СУММА
label-caps · 12px/16px · 600
Заголовки колонок таблиц и надписи над группами: капсом.
01
section-num · 24px/32px · 700
Синий номер раздела перед заголовком h1.
39 100,00
num-xl · 24px/32px · 600
Итог документа и чека, текущее значение барабана времени.
1 250,00
num-l · 20px/28px · 600
Суммы и коды в карточках: табличные цифры.
3
num-b · 17px/24px · 600
Цифры в контролах: счётчик, соседние значения барабана.
1 234 567 890
num-m · 14px/20px · 500
Цены, время, номера в строках и таблицах.
1 × 9 400,00
num-s · 13px/18px · 400
Подстрока чека «1 × 9 400,00», номер под названием.
04

Сетка, радиусы, тени

Шаг сетки — 4 px. Радиусы — от чипа до капсулы. Тени — только для того, что плавает над контентом.

space-2 · 2px
Микрозазор: иконка ↔ бейдж.
space-4 · 4px
Базовый шаг сетки. Зазор иконка ↔ подпись в таб-баре.
space-6 · 6px
Внутренний отступ пилюли активного таба по вертикали.
space-8 · 8px
Зазор между чипами, inset XXS.
space-10 · 10px
Вертикальный паддинг чипа.
space-12 · 12px
Gutter сетки, gap внутри кнопки, вертикаль строки, заголовок секции → карточка.
space-16 · 16px
Поля экрана, отступ острова от краёв экрана, паддинг поля ввода.
space-20 · 20px
Паддинг карточки-острова и нижней панели, горизонталь строки.
space-24 · 24px
Горизонтальный паддинг кнопок L и M.
space-32 · 32px
Между секциями экрана.
radius-6 · 6px
Плашка inline-кода в тексте и Markdown.
radius-12 · 12px
Квадратик-номер в карточке выбора, чипы.
radius-16 · 16px
Карточки-факты, тост-алерт, ячейка кода.
radius-20 · 20px
Поле ввода, карточка выбора.
radius-22 · 22px
Острова — главный радиус системы (как в документах).
radius-28 · 28px
Обложка-герой.
radius-40 · 40px
Нижний лист: все углы на среднем детенте, верхние — на полном.
radius-pill · 1000px
Кнопки, капсула-метка, таб-бар, свитч, сегмент.
shadow-island · 0 8px 24px rgba(9, 9, 9, 0.10)
Отрыв острова (таб-бар, плавающая кнопка, тост) от контента.
shadow-tooltip · 0 8px 16px rgba(9, 9, 9, 0.12)
Подсказки и выпадающие меню.
shadow-focus · 0 0 0 2px #FFFFFF, 0 0 0 4px #0071E3
Кольцо фокуса клавиатуры на любом контроле: 2px зазор + 2px accent, 3,85:1 и выше на любой поверхности.
05

Движение

Пять длительностей и четыре кривые. Мелкое переключается быстро, крупное появляется мягко и уходит быстрее, чем пришло. При «Уменьшить движение» в системе анимации отключаются.

100ms
duration-instant
Отклик на нажатие: затемнение кнопки, чипа, иконки.
160ms
duration-fast
Мелкие переключения на месте: свитч, чип, сегмент, выбор карточки.
240ms
duration-base
Тост и алерт, смена вкладки, раскрытие строки.
360ms
duration-slow
Нижний лист и диалог: появление вместе с затемнением.
480ms
duration-page
Переход между экранами.
(0.2, 0, 0, 1)
ease-standard
Движение внутри экрана: элемент был и остаётся видимым.
(0, 0, 0, 1)
ease-enter
Появление: быстро входит и мягко тормозит (лист, тост, экран).
(0.3, 0, 1, 1)
ease-exit
Уход: плавно трогается и быстро исчезает. Длительность ×0,75 от появления.
(0.34, 1.4, 0.64, 1)
ease-spring
Пружина с лёгким перелётом: кноб свитча, всплывающая капсула. Не для текста и больших площадей.

Длительности

instant
fast
base
slow
page

Кривые

standard
enter
exit
spring

Замедлено до 1,2 с, чтобы была видна форма кривой.

Тост

Сохранено

duration-base + ease-enter, уход — ease-exit за 180 мс.

Нижний лист

Нижний листНажмите на затемнение, чтобы закрыть.

duration-slow + ease-enter; затемнение — ease-standard.

Переход экрана

Задачи
Карточка задачи

duration-page + ease-standard; прошлый экран сдвигается на треть.

06

Состояния

У всего, что нажимается, пять состояний. Слой — цвет содержимого поверх фона: ховер 6 %, нажатие 12 % и мягкий риппл из точки касания, обрезанный по форме, плюс сжатие до 0,97 на пружине. Ховер — только там, где есть мышь. Фокус с клавиатуры — синее кольцо.

КомпонентПокойХоверНажатиеФокусНедоступно
Primary
Accent
Secondary
Ghost
Danger
Chip
IconButton

Попробуйте

Наведите, нажмите и подержите, пройдите Tab-ом.

Контраст текста

WCAG, слой поверх фона учтён. Норма для текста — 4,5.

КнопкаСветлая: покой · ховер · нажатиеТёмная: покой · ховер · нажатие
Primary16.8 · 13.2 · 10.019.3 · 16.6 · 13.9
Accent4.7 · 5.7 · 6.94.7 · 5.7 · 6.9
Secondary / Chip13.8 · 12.3 · 10.912.8 · 10.7 · 8.9
Ghost5.6 · 5.1 · 4.77.0 · 6.6 · 6.3
Danger5.9 · 5.3 · 4.87.6 · 7.2 · 6.7
07

Компоненты

30 живых компонентов — настоящий HTML и CSS системы, не картинки. Всё нажимается: свитчи, счётчики, календарь, колёса времени, поля ввода. В Compose — те же имена и параметры. Данные в примерах демонстрационные.

Действия

Button

Капсульная кнопка: контрастная primary для главного действия, синяя accent для оплаты и брендовых моментов, серая secondary, текстовая ghost, контурная danger.

CtaIsland

Контрастный остров inverse «Следующий шаг» в конце экрана или документа: одна фраза и одна кнопка.

IconButton

Круглая кнопка 48 с иконкой 24: серая без рамки, стеклянная поверх контента, primary для главного действия.

Ввод

Chip

Капсула-фильтр 36; выбранный — инверсия primary / on-primary.

ChoiceCard

Карточка варианта с квадратиком-номером primary: 2–3 варианта на выбор.

CodeInput

Поле кода из SMS и PIN: отдельные ячейки 56 с радиусом 16, 4 или 6 цифр, вставка всего кода и автозаполнение из SMS.

DatePicker

Выбор даты и периода: поле с иконкой календаря и месяц на сером острове.

Segmented

Сегмент-капсула: выбор одного из 2–4 вариантов на месте.

Stepper

Счётчик количества: серая капсула с «−», числом и «+».

Switch

Переключатель 52×32: включён — синий трек.

TextField

Поле ввода: подпись над полем, капсула 56 с радиусом 20 на bg.

TimePicker

Выбор времени: поле с часами и барабан часов и минут, текущее значение на выделенной полосе.

Навигация

TabBar

Нижняя навигация: стеклянная капсула 64 с «таблеткой» bg под активным разделом; главное действие — круг primary справа.

TopBar

Тулбар 64: на вкладке крупный заголовок слева, на вложенном экране заголовок по центру между круглыми кнопками.

Поверхности

BottomSheet

Нижний лист как в iOS: парит с отступом 8 и скруглён со всех сторон (40), при полном раскрытии плавно встаёт до краёв. Иконка в круге, заголовок, текст и действия внизу.

Cover

Dialog

Модальный диалог по центру над scrim: подтверждение необратимого действия или блокирующая ошибка.

Hero

Чёрная обложка-герой, как обложка наших документов: капсула-метка, крупный заголовок, подзаголовок и ряд фактов.

Island

Серая карточка-остров с радиусом 22 — основной блок контента, как острова в документах.

Данные

Document

Лист документа (счёт, акт, договор) в стиле наших ТЗ: лист bg с рамкой line на острове surface, тот же порядок блоков.

ListRow

Строки в сгруппированном списке на острове, как настройки iOS: иконка в квадратике, заголовок, справа значение, сумма, свитч или шеврон.

Receipt

Чек об оплате: бумажная лента с зубчатым нижним краем, все суммы моноширинным шрифтом.

TableIsland

Таблица внутри серого острова: заголовки капсом, цифры справа, жирная строка «Итого».

Tag

Капсула-метка высотой 28: срок, статус, черновик.

Обратная связь

PushNotification

Пуш-уведомление: стеклянная карточка r22 с иконкой приложения, названием модуля, временем, заголовком и текстом.

StateView

Состояния экрана: загрузка, пусто, ошибка, нет сети — на острове, у каждого своё действие.

Toast

Тост — тёмная капсула внизу экрана (тёмная в обеих темах); алерт — остров статуса внутри экрана.

Текст

SectionHeader

Заголовок раздела с синим номером «01, 02…», как в документах.

Камера

Camera

Экран камеры: всегда тёмный в обеих темах — на токенах обложки hero.

Scanner

Сканер штрихкода и QR: окно сканирования над затемнением, синий луч и карточка найденного объекта снизу.

08

Иконки

169 контурных иконок Lucide 0.454.0, сетка 24 × 24, линия 2. Красятся цветом текста. Нажмите — имя скопируется.

09

Код

Один tokens.json → генераторы → CSS-переменные и Kotlin. Тема переключается целиком, компоненты не знают про hex.

ContinueButton.ktKotlin
SshTheme(mode = SshThemeMode.System) {    SshButton(        text = "Продолжить",        onClick = onNext,        variant = SshButtonVariant.Primary,        size = SshButtonSize.L,    )}
index.htmlHTML
<link rel="stylesheet" href="tokens.css"><link rel="stylesheet" href="ssh.css"> <body class="ssh">  <button class="ssh-btn l primary block">    Продолжить  </button></body>
TaskScreen.ktKotlin
@Composablefun TaskScreen(    state: TaskState,    onToggle: (taskId: String) -> Unit,    onCreate: () -> Unit,    modifier: Modifier = Modifier,) {    // Экран собирается как документ: заголовок, острова, главное действие внизу.    Column(        modifier = modifier            .fillMaxSize()            .background(color = SshTheme.colors.bg)            .padding(horizontal = SshSpacing.Space16),        verticalArrangement = Arrangement.spacedBy(space = SshSpacing.Space12),    ) {        SshTopBar(title = "Задачи")        SshSegmented(            items = listOf("Все", "Сегодня", "Готово"),            selectedIndex = state.filter.ordinal,            onSelect = state::selectFilter,        )        SshIsland {            state.tasks.forEach { task ->                SshListRow(                    title = task.title,                    subtitle = task.due,                    trailing = {                        SshSwitch(                            checked = task.done,                            onCheckedChange = { onToggle(task.id) },                        )                    },                )            }        }        Spacer(modifier = Modifier.weight(weight = 1f))        SshButton(            text = "Новая задача",            onClick = onCreate,            modifier = Modifier.fillMaxWidth(),        )    }}
sheet.cssCSS
.sheet {  transform: translateY(100%);  transition: transform var(--duration-slow) var(--ease-enter);}.sheet.open { transform: none; }
10

Markdown

Заметки, справка, ответы ассистента — тем же языком, что документы: цитата — выделенный остров, код и таблица — серые острова. Слева исходник, справа результат. Compose: SshMarkdown(markdown = text), веб: <div class="ssh-md">.

notes.mdMarkdown
# Заметки к релизу Версия **0.2** добавляет *Markdown* и ~~старый~~ новый блок кода. Подробности — в [документации](https://sshorg.com/design/), токены — в `tokens.json`. ## Что внутри — 3 блока - Заголовки, абзацы, **жирный**, *курсив*, `код`- Списки любой вложенности  - вложенный пункт- Таблицы и цитаты-острова 1. Подключить библиотеку2. Обернуть экран в `SshTheme`3. Передать текст в `SshMarkdown` ### Задачи - [x] Парсер GFM- [x] Подсветка кода- [ ] Картинки через загрузчик приложения > **Важно:** компонент берёт цвета только из темы — светлая и тёмная работают без настроек. ```kotlin@Composablefun Notes(text: String) {    SshMarkdown(        markdown = text,        onLinkClick = { url -> openUrl(url) },    )}``` | Элемент | Токен | Размер ||:--|:--|--:|| Остров | `surface` | 22 || Код | `surface` | 13 || Цитата | `accent-soft` | 22 | --- Сноска: длинные строки кода прокручиваются, а не переносятся.

Заметки к релизу

Версия 0.2 добавляет Markdown и старый новый блок кода. Подробности — в документации, токены — в tokens.json.

Что внутри — 3 блока

  • Заголовки, абзацы, жирный, курсив, код
  • Списки любой вложенности
    • вложенный пункт
  • Таблицы и цитаты-острова
  1. Подключить библиотеку
  2. Обернуть экран в SshTheme
  3. Передать текст в SshMarkdown

Задачи

Важно: компонент берёт цвета только из темы — светлая и тёмная работают без настроек.

Kotlin
@Composablefun Notes(text: String) {    SshMarkdown(        markdown = text,        onLinkClick = { url -> openUrl(url) },    )}
Элемент Токен Размер
Остров surface 22
Код surface 13
Цитата accent-soft 22

Сноска: длинные строки кода прокручиваются, а не переносятся.

Kotlin 2.4 · Compose Multiplatform 1.12

Android, iOS, Desktop. Тесты контраста AA в обеих темах.

Наверх