Button
Капсульная кнопка: контрастная primary для главного действия, синяя accent для оплаты и брендовых моментов, серая secondary, текстовая ghost, контурная danger.
Набор токенов, компонентов и правил для мобильных и веб-продуктов. Один источник — tokens.json — и из него CSS и Compose Multiplatform для Android, iOS и Desktop.
Экран собирается как хороший документ: белый лист, серые острова, чёрное главное действие и один синий акцент.
Главное действие — чёрная капсула primary. Синий accent — фокус, выбор, оплата. Остальное — белый, серый, чёрный.
Навигация плавает отдельными капсулами над контентом. Контент — плоские серые Island на белом фоне.
Главная кнопка внизу, во всю ширину, 56 px. Цель касания — не меньше 48 px.
Пары текст/фон проходят WCAG AA в обеих темах — это проверяет автотест, а не глаз.
43 семантических токена. Каждый задан для светлой и тёмной темы — переключите тему наверху, образцы перекрасятся. Значения: светлая · тёмная.
ink, ink-2, accent-text.ink (не ink-2).scrim: нижний лист, диалог. В тёмной теме светлее bg, иначе лист сливается с затемнением.elevated (в тёмной теме surface совпал бы с листом).blur-*.bg и surface в обеих темах.bg и surface. На surface-2 не ставить.accent-fill. Как текст — только на bg; иначе accent-text.accent тёмной темы под текст не годится.accent-fill.accent-fill и accent-pressed — белый в обеих темах.accent-soft.bg, surface, surface-2).danger-soft.success-soft.bg, surface, warning-soft.warning-soft.accent-soft (отдельного синего нет, чтобы не спорить с акцентом).primary.primary и primary-pressed.inverse.#1D1D1F, чтобы не слиться с фоном.hero.hero и hero-2.hero и hero-2 (≥4,8:1).hero, декоративная.Системный шрифт платформы: San Francisco на Apple, Roboto на Android, системный на вебе. Файлы шрифтов не поставляются — нечего лицензировать. Цифры — моноширинные.
Шаг сетки — 4 px. Радиусы — от чипа до капсулы. Тени — только для того, что плавает над контентом.
accent, 3,85:1 и выше на любой поверхности.Пять длительностей и четыре кривые. Мелкое переключается быстро, крупное появляется мягко и уходит быстрее, чем пришло. При «Уменьшить движение» в системе анимации отключаются.
100ms160ms240ms360ms480ms(0.2, 0, 0, 1)(0, 0, 0, 1)(0.3, 0, 1, 1)(0.34, 1.4, 0.64, 1)Замедлено до 1,2 с, чтобы была видна форма кривой.
duration-base + ease-enter, уход — ease-exit за 180 мс.
duration-slow + ease-enter; затемнение — ease-standard.
duration-page + ease-standard; прошлый экран сдвигается на треть.
У всего, что нажимается, пять состояний. Слой — цвет содержимого поверх фона: ховер 6 %, нажатие 12 % и мягкий риппл из точки касания, обрезанный по форме, плюс сжатие до 0,97 на пружине. Ховер — только там, где есть мышь. Фокус с клавиатуры — синее кольцо.
| Компонент | Покой | Ховер | Нажатие | Фокус | Недоступно |
|---|---|---|---|---|---|
| Primary | |||||
| Accent | |||||
| Secondary | |||||
| Ghost | |||||
| Danger | |||||
| Chip | |||||
| IconButton |
Наведите, нажмите и подержите, пройдите Tab-ом.
WCAG, слой поверх фона учтён. Норма для текста — 4,5.
| Кнопка | Светлая: покой · ховер · нажатие | Тёмная: покой · ховер · нажатие |
|---|---|---|
| Primary | 16.8 · 13.2 · 10.0 | 19.3 · 16.6 · 13.9 |
| Accent | 4.7 · 5.7 · 6.9 | 4.7 · 5.7 · 6.9 |
| Secondary / Chip | 13.8 · 12.3 · 10.9 | 12.8 · 10.7 · 8.9 |
| Ghost | 5.6 · 5.1 · 4.7 | 7.0 · 6.6 · 6.3 |
| Danger | 5.9 · 5.3 · 4.8 | 7.6 · 7.2 · 6.7 |
30 живых компонентов — настоящий HTML и CSS системы, не картинки. Всё нажимается: свитчи, счётчики, календарь, колёса времени, поля ввода. В Compose — те же имена и параметры. Данные в примерах демонстрационные.
Капсульная кнопка: контрастная primary для главного действия, синяя accent для оплаты и брендовых моментов, серая secondary, текстовая ghost, контурная danger.
Контрастный остров inverse «Следующий шаг» в конце экрана или документа: одна фраза и одна кнопка.
Круглая кнопка 48 с иконкой 24: серая без рамки, стеклянная поверх контента, primary для главного действия.
Капсула-фильтр 36; выбранный — инверсия primary / on-primary.
Карточка варианта с квадратиком-номером primary: 2–3 варианта на выбор.
Поле кода из SMS и PIN: отдельные ячейки 56 с радиусом 16, 4 или 6 цифр, вставка всего кода и автозаполнение из SMS.
Выбор даты и периода: поле с иконкой календаря и месяц на сером острове.
Сегмент-капсула: выбор одного из 2–4 вариантов на месте.
Счётчик количества: серая капсула с «−», числом и «+».
Переключатель 52×32: включён — синий трек.
Поле ввода: подпись над полем, капсула 56 с радиусом 20 на bg.
Выбор времени: поле с часами и барабан часов и минут, текущее значение на выделенной полосе.
Нижняя навигация: стеклянная капсула 64 с «таблеткой» bg под активным разделом; главное действие — круг primary справа.
Тулбар 64: на вкладке крупный заголовок слева, на вложенном экране заголовок по центру между круглыми кнопками.
Нижний лист как в iOS: парит с отступом 8 и скруглён со всех сторон (40), при полном раскрытии плавно встаёт до краёв. Иконка в круге, заголовок, текст и действия внизу.
Модальный диалог по центру над scrim: подтверждение необратимого действия или блокирующая ошибка.
Чёрная обложка-герой, как обложка наших документов: капсула-метка, крупный заголовок, подзаголовок и ряд фактов.
Серая карточка-остров с радиусом 22 — основной блок контента, как острова в документах.
Лист документа (счёт, акт, договор) в стиле наших ТЗ: лист bg с рамкой line на острове surface, тот же порядок блоков.
Строки в сгруппированном списке на острове, как настройки iOS: иконка в квадратике, заголовок, справа значение, сумма, свитч или шеврон.
Чек об оплате: бумажная лента с зубчатым нижним краем, все суммы моноширинным шрифтом.
Таблица внутри серого острова: заголовки капсом, цифры справа, жирная строка «Итого».
Капсула-метка высотой 28: срок, статус, черновик.
Пуш-уведомление: стеклянная карточка r22 с иконкой приложения, названием модуля, временем, заголовком и текстом.
Состояния экрана: загрузка, пусто, ошибка, нет сети — на острове, у каждого своё действие.
Тост — тёмная капсула внизу экрана (тёмная в обеих темах); алерт — остров статуса внутри экрана.
Заголовок раздела с синим номером «01, 02…», как в документах.
Экран камеры: всегда тёмный в обеих темах — на токенах обложки hero.
Сканер штрихкода и QR: окно сканирования над затемнением, синий луч и карточка найденного объекта снизу.
169 контурных иконок Lucide 0.454.0, сетка 24 × 24, линия 2. Красятся цветом текста. Нажмите — имя скопируется.
Ничего не найдено
Один tokens.json → генераторы → CSS-переменные и Kotlin. Тема переключается целиком, компоненты не знают про hex.
SshTheme(mode = SshThemeMode.System) { SshButton( text = "Продолжить", onClick = onNext, variant = SshButtonVariant.Primary, size = SshButtonSize.L, )}<link rel="stylesheet" href="tokens.css"><link rel="stylesheet" href="ssh.css"> <body class="ssh"> <button class="ssh-btn l primary block"> Продолжить </button></body>@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 { transform: translateY(100%); transition: transform var(--duration-slow) var(--ease-enter);}.sheet.open { transform: none; }Заметки, справка, ответы ассистента — тем же языком, что документы: цитата — выделенный остров, код и таблица — серые острова. Слева исходник, справа результат. Compose: SshMarkdown(markdown = text), веб: <div class="ssh-md">.
# Заметки к релизу Версия **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.
кодSshThemeSshMarkdownВажно: компонент берёт цвета только из темы — светлая и тёмная работают без настроек.
@Composablefun Notes(text: String) { SshMarkdown( markdown = text, onLinkClick = { url -> openUrl(url) }, )}| Элемент | Токен | Размер |
|---|---|---|
| Остров | surface |
22 |
| Код | surface |
13 |
| Цитата | accent-soft |
22 |
Сноска: длинные строки кода прокручиваются, а не переносятся.
Android, iOS, Desktop. Тесты контраста AA в обеих темах.