brandbook.x-dragon.com / ui

Інтерфейсна система

Форма, ритм, стани й компоненти для всіх елементів інтерфейсу. Кожен блок — це правило і поруч живий приклад, з якого можна копіювати. Палітра й ролі кольору — у розділі Колір брендбуку.

01

Форма

Один жест на всю систему: три кути скруглені на 5 px, нижній лівий замінений на гостру діагональ 45°. Розмір зрізу береться зі сходинки, а не рахується з висоти елемента.

Сходинка зрізу

Зріз залежить від розміру елемента, але не пропорційно: чекбокс віддає під нього 23 % висоти, панель — 7 %. П'ять значень покривають усе, проміжних не буває.

xs · 5px
до 24 px
чекбокс, тег
sm · 5.6px
26–36 px
чип, малий btn
md · 8.4px
38–56 px
кнопка, поле
lg · 12.6px
57–140 px
тулбар, меню
xl · 18.2px
понад 140 px
панель, картка

Базові значення 5 / 8 / 12 / 18 / 26 множаться на --k: 0.7. Крок xs має підлогу 5 px: нижче цього зріз перестає читатися на звичайному екрані.

Тонкі елементи

Смуга заввишки 6–18 px зрізу не витримує — він з'їв би всю висоту. Такі елементи нахиляють ліву грань цілком на 10°, радіус падає до 2 px. Дрібні квадратні плашки — бігунок, ручка слайдера — лишаються зі зрізом xs: у них висота і ширина одного порядку.

Draft v6.2 online

Правила

Так

  • Один зріз на групу: у сегментах і табах ріже тільки перший елемент
  • У вертикальному списку зріз бере контейнер, рядки лишаються квадратними
  • Найдрібніша плашка теж має зріз: бігунок 14 px бере крок xs
  • Радіус завжди менший за зріз, інакше кут «з'їдає» діагональ
  • У RTL жест дзеркалиться: зріз і акцентна смуга йдуть до початкової грані

Ні

  • Зріз на кожному рядку списку — нижня кромка стає пилкою
  • border, outline і box-shadow на елементі зі зрізом: кліп їх ріже
  • Проміжні розміри зрізу «на око» замість сходинки
  • Компенсація padding під зріз: вміст стоїть по центру, кут вільний
  • Зріз в іншому куті або під іншим кутом на одному екрані

Пилка проти контейнера

Так: зріз у контейнера, рядки квадратні
Ні: зріз на кожному рядку
02

Ритм і розмір

Відступи — крок 4 px, вісім значень. Висоти контролів — чотири, і кожна прив'язана до свого кроку зрізу. Проміжних значень у системі немає.

Відступи

--sp-14 px · всередині дрібних елементів
--sp-28 px · іконка й текст
--sp-312 px · між контролами
--sp-416 px · padding рядка
--sp-524 px · padding картки
--sp-632 px · між блоками
--sp-748 px · між групами
--sp-864 px · між секціями

Висоти контролів

xs · 28 Чип зріз sm · щільні панелі, тулбари
sm · 36 зріз sm · вторинні дії, сегменти
md · 44 зріз md · базовий розмір
lg · 52 зріз md · головна дія на екрані
Чому не пропорційно. Якщо прив'язати зріз до висоти у відсотках, 44-піксельна кнопка і 300-піксельна панель отримають різні за характером кути: один майже непомітний, другий з'їдає половину грані. Сходинка з п'яти значень тримає жест однаковим на всіх масштабах, і саме тому він читається як підпис бренду.
03

Типографіка інтерфейсу

Сім кроків кегля, три інтерліньяжі. Все, що в інтерфейсі, живе тільки в цих значеннях — на відміну від текстових сторінок, де шкала ширша.

Заголовок екрана --fs-700 · 26/1.2 · Montserrat 600
Заголовок блока --fs-600 · 20/1.2 · Montserrat 600
Назва картки --fs-500 · 17/1.2 · Montserrat 600
Базовий текст інтерфейсу і поля вводу --fs-400 · 15/1.4 · Inter 400
Другорядний текст, компактні рядки --fs-300 · 13/1.4 · Inter 400
Лейбли полів, чипи, підказки --fs-200 · 12/1.4 · Inter 400–500
Мета, теги, значення --fs-100 · 11/1.4 · JetBrains Mono

Так

  • Інтерліньяж 1.2 для заголовків, 1.4 для UI, 1.6 для абзаців
  • Uppercase — тільки мono 11 px з letter-spacing +10 %
  • Мінімальний кегль у продукті — 11 px, і лише для мета-даних
  • Вага 400 і 500 для тексту, 600 для заголовків

Ні

  • Проміжні кеглі на кшталт 11.5 або 13.5 px
  • Капс на Inter довшими за два слова
  • Більше двох ваг у межах одного блока
  • Cormorant SC в інтерфейсі: він для обкладинок, не для UI
04

Стани

Шість станів на кожен інтерактивний елемент. Стан ніколи не передається лише кольором — завжди є друга ознака: яскравість, маркер або позиція.

default Navy, текст 500
hover яскравість ×1.14, 120 ms
active яскравість ×0.92, без зсуву
focus кільце 2 px Azure по силуету
disabled opacity 0.5, курсор not-allowed
loading спінер замість тексту, ширина не стрибає

Фокус

outline і box-shadow зрізаються кліпом, тому фокус для елементів зі зрізом — стек із чотирьох drop-shadow: він повторює силует. Спробуйте Tab.

Обмеження прийому. filter створює containing block: абсолютно спозиційовані нащадки всередині сфокусованого елемента почнуть рахувати координати від нього, а position: fixed перестане бути fixed. Тому кільце вішаємо на сам контрол, а не на контейнер із поповерами всередині.

Стан не тільки кольором

Так

Активний Збій

Колір плюс іконка й підпис.

Ні

Тільки крапка: не читається при дальтонізмі.

05

Рівні й тіні

Три поверхні для площин і три тіні для того, що спливає над ними. Тінь — це drop-shadow на батьківському елементі, бо box-shadow ріжеться кліпом.

base #0D1011 · тло сторінки
surface #161A1D · картки, панелі, поля
surface-2 #22272B · вкладене, меню, чипи

Тінь по силуету

Зліва направо: --shadow-1 для наведеної картки, --shadow-2 для меню й поповерів, --shadow-3 для модалок. Тінь висить на обгортці без кліпу — drop-shadow обводить зрізаний силует, а не прямокутник.

Поповери — тільки через портал. clip-path контейнера зрізає і абсолютно спозиційованих нащадків, тому меню, тултип і дропдаун у продакшені виносимо в body. Усередині картки вони працюватимуть лише поки поміщаються в її межі.
06

Компоненти

Повний набір елементів у формі бренду — з них збираються екрани.

Кнопки

Групи

сегменти
таби
тулбар

Поля

Вибір

Два маркери на всю систему: гостра галочка під 45° і ромб. Кіл немає ніде — радіо відрізняється від чекбокса маркером, а не формою рамки.

Чипи, теги, аватари

Neutral Solid Info Success Warning Danger
draft v6.2 online beta down БФ ІК ОД

Прогрес і слайдер

64
1 2 3

Повідомлення

Оновлення доступне

Акцент — смуга в самому фоні блока, чверть від зрізу. Низ у неї той самий 45°, що й кут.

Розгорнуто

Вузол eu-central-04 піднявся за 27 секунд.

Квота майже вичерпана

Лишилося 8 % ліміту на поточний місяць.

Реплікація зупинена

Останній успішний запис — 14 хвилин тому.

Списки й меню

Рядок квадратний — у списку зріз належить контейнеру. Жест лишається на акценті: смуга завширшки з половину зрізу, а її низ зрізаний під ті самі 45°, тож вона закінчується вістрям.

Таблиця й пагінація

ВузолРегіонСтанНавантаження
eu-central-01Франкфуртonline62 %
eu-central-02Франкфуртdegraded91 %
us-east-01Ешбернdown
3 з 24 вузлів

Порожній стан і тултип

Перетягніть файли сюди

Кліп ріже пунктирну рамку, тому зону позначає штрихування під кутом зрізу.

Останній запис 14 хв тому Тултип — surface-2, 12 px, без стрілки:
стрілка не переживає кліп.
07

Рух

Три тривалості й одна крива. Рух пояснює зміну стану, а не прикрашає її.

--dur-1120 ms · колір, прозорість, hover
--dur-2180 ms · позиція й розмір, перемикач
--dur-3260 ms · поява панелей і меню

Крива одна: cubic-bezier(.4, 0, .2, 1). Bounce і pulse у системі відсутні.

Reduced motion. При prefers-reduced-motion: reduce всі переходи й анімації стискаються до 1 ms, спінер зупиняється на одному оберті. Стан має лишатися зрозумілим і без руху — саме тому в кожного стану є друга ознака, крім анімації.
08

Токени

Повний набір змінних: спершу бренд — колір, градієнт і шрифти, далі все, з чого складається інтерфейс. Копіюється у проєкт як є.

:root {
  /* Нейтралі */
  --color-base:      #0D1011;
  --color-surface:   #161A1D;
  --color-surface-2: #22272B;
  --color-border:    #3B444B;
  --color-pigeon:    #8B959C;
  --color-text:      #F1F2F3;

  /* Ядро бренду й акценти */
  --brand-violet:  #321467;
  --brand-navy:    #263ABA;
  --brand-ocean:   #4389E5;
  --brand-azure:   #A2C9F6;
  --brand-flame:   #FE9B22;
  --brand-coral:   #F86570;

  --gradient-brand: linear-gradient(120deg, #321467 0%, #263ABA 42%, #4389E5 100%);

  /* Другим у стеку йде затверджений fallback */
  --font-display: "Cormorant SC", Georgia, "Times New Roman", serif;  /* H1, вага 500 */
  --font-heading: "Montserrat", Arial, Helvetica, sans-serif;         /* H2, H3, вага 600 */
  --font-body:    "Inter", Arial, Helvetica, sans-serif;
  --font-mono:    "JetBrains Mono", "Courier New", monospace;

  /* Форма */
  --ca: 45deg;                          /* кут зрізу */
  --k: 0.7;                             /* масштаб сходинки */
  --r: 5px;                             /* радіус трьох інших кутів */
  --angle: 10deg;                       /* нахил тонких елементів */
  --cut-xs: max(5px, calc(5px * var(--k)));
  --cut-sm: calc(8px * var(--k));
  --cut-md: calc(12px * var(--k));
  --cut-lg: calc(18px * var(--k));
  --cut-xl: calc(26px * var(--k));
  --shape-min: 12px;                    /* нижче живуть тільки маркери */

  /* Ритм */
  --sp-1: 4px;   --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 24px;  --sp-6: 32px;  --sp-7: 48px;  --sp-8: 64px;

  /* Висоти контролів */
  --h-xs: 28px;  /* зріз sm */
  --h-sm: 36px;  /* зріз sm */
  --h-md: 44px;  /* зріз md — базова */
  --h-lg: 52px;  /* зріз md */

  /* Типографіка */
  --fs-100: 11px; --fs-200: 12px; --fs-300: 13px; --fs-400: 15px;
  --fs-500: 17px; --fs-600: 20px; --fs-700: 26px;
  --lh-tight: 1.2; --lh-ui: 1.4; --lh-text: 1.6;

  /* Структурний колір */
  --color-separator: #3B444B;   /* декоративні лінії, 1.8:1 */
  --color-line:      #697680;   /* межі контролів, 3.8:1 */
  --color-placeholder: #7C868D; /* 5.1:1 на base */

  /* Семантика */
  --info:    #4389E5;  --info-fg:    #A2C9F6;  --info-bg:    rgba(67,137,229,.14);
  --success: #3FBF8F;  --success-fg: #6FD9B0;  --success-bg: rgba(63,191,143,.14);
  --warning: #FE9B22;  --warning-fg: #FFC178;  --warning-bg: rgba(254,155,34,.14);
  --danger:  #F86570;  --danger-fg:  #FA8B93;  --danger-bg:  rgba(248,101,112,.14);
  --on-solid: #0D1011;          /* текст на суцільній заливці ролі */

  --focus: #A2C9F6;
  --disabled-opacity: .5;

  /* Рівні: box-shadow ріжеться кліпом, тому тінь — filter на обгортці */
  --shadow-1: drop-shadow(0 2px 6px rgba(0,0,0,.4));
  --shadow-2: drop-shadow(0 10px 24px rgba(0,0,0,.5));
  --shadow-3: drop-shadow(0 22px 50px rgba(0,0,0,.6));

  /* Рух */
  --dur-1: 120ms; --dur-2: 180ms; --dur-3: 260ms;
  --ease: cubic-bezier(.4, 0, .2, 1);
}
Дві форми — два класи. .ch для плашок (модифікатори --xs--xl перемикають крок сходинки), .sl для тонких смуг. Обидва — чистий CSS без JS: розмір зрізу абсолютний, тому висоту міряти не треба.
Звідки беруться кольори. Палітра, семантичні ролі та виміряний контраст описані в розділі Колір брендбуку — тут вони лише зібрані у змінні.