Компонент · рівень 1

Дія стовпчиком

Мітка над підписом. Контрол, названий малюнком зі словом під ним - одне натискання, один напрямок.

рівень 1design/system/components/stack-action.css2 організми8 входжень
Цього атома не існувало, хоча він був написаний двічі

Крок 7.18: два словники на ті самі три частини

Форму написали всередині двох організмів і назвали іменами організмів. Жодне з імен не каже, що це таке насправді:

контролміткапідпислічильникфайл
шапка.wfh-act.stack.g.lbl.hbheader.css
таб-бар.wf-tab.ti.tl.tbadgetabbar.css

Найпереконливіше не те, що розійшлось, а те, що збіглось: gap: 2px в обох. Крок 7.17 вивів цю двійку з бюджету шапки в 44px, жодного разу не заглянувши в таб-бар, де вона стояла давно. Коли два незалежні проходи над одним контролом дають однакове число, це не збіг - це атом, якого ніхто не назвав. Підпис теж збігався: 12px, semibold, у спокої.

А це вже розійшлось, бо два видання завжди розходяться

ВісьШапкаТаб-барЗведено
гліф202120 - сходинка набору; 21 було випадковістю 1.05em на 20-піксельному емодзі
чорнило підпису--text-secondary--text-muted--text-secondary - слово під міткою це частина імені контрола, а не приглушений шум поруч
інтерліньяж підписуflat19.2pxflat - підпис під міткою це один рядок за визначенням

Обидва числа - рішення власника, сказані вголос, а не всереднені.

Анатомія
Обране 6Обране Кабінет 3Кошик Головна
наведіть - у перших трьох приходить теплий ґрунт, а мітка і підпис разом ідуть в акцент; четвертий і п'ятий не рухаються, бо в таб-бара немає фінішу, і це правильно

Перші три - як у шапці (.g / .lbl / .hb), четвертий і п'ятий - як у таб-барі (.ti / .tl / .tbadge). Одне правило, два словники, і зовні їх не відрізнити - у цьому й був сенс кроку.

П'ятий - активна вкладка, і це єдине, чим таб-бар відрізняється на екрані: акцентна смуга зверху й підпис чорнильний / 800. Смугу малює .wf-tab[aria-current="page"]::before, чорнило - .wf-tab[aria-current] .tl, обидва в tabbar.css, а не тут. Атом дає position:relative, від якого смуга рахує свій верх - решта організмова. У шапці такого стану немає: дія шапки нікуди не «поточна».

1Мітка - 20, сходинка M набору. Її читають першою, тому вона більша за підпис під нею
2Проміжок 2 - і він мусить бути меншим за повітря навколо пари, інакше близькість каже, що мітка й підпис належать одне одному менше, ніж кожне - краю кнопки
3Підпис - 12 / semibold / --text-secondary, інтерліньяж flat
4Лічильник - висить на мітці, бо рахує те, що мітка позначає, а не те, що підпис називає

Це розмітка продукту з wireframes/_nav.js. Клас btn--stack доданий до старих імен, а не замість них: .g, .lbl, .ti, .tl живуть і в wireframes/, замороженому з етапу 05. Додати клас безпечно в обидва боки, перейменувати - ні, тож атом сьогодні відгукується на обидва словники. Перейменування - пункт Кроку 6.

Однакове й різне: два входження поруч

Виміряно на живих екранах після зведення. Однакове - те, що атом оголошує. Різне - те, що належить організму, який контрол ставить.

Шапка (≥1024)Таб-бар (≤859)Чиє
напрямcolumncolumnатом
проміжок22атом
гліф2020атом
підпис12 / 600 / #5B5B5412 / 600 / #5B5B54атом
висота коробки4450організм
повітря зверху / знизу5 / 58 / 8організм
активний станнемає[aria-current]: акцентна смуга зверху, підпис чорнильний і blackорганізм
місце лічильникакут міткиосьова лінія вкладкиатом, дві прив\'язки

ПОВЕДІНКА НА ШИРИНІ - етап 10, крок 4

Від якого порогу: жодного. Що саме міняється: колонка тримає відсоткову ширину і власну стелю. Плинне з самого початку.
Коли вживати

Коли контрол має бути вузьким і впізнаваним з відстані: ряд дій у шапці на десктопі й таб-бар на телефоні. Мітка тримає впізнавання, підпис знімає загадку - принцип 5, «звичайні слова в підписах». Якщо місця вистачає на рядок, беріть звичайну Кнопку: стовпчик коштує висоти.

Правило і антиправило

Правило

Проміжок усередині менший за повітря навколо. Мітка й підпис це одна річ, і відстань має це казати. До кроку 7.17 у шапці було 8 усередині і 1.2 назовні - групування читалось навиворіт, і око це бачило, не вміючи назвати.

Антиправило

Не давай підпису overflow:hidden без flex:none. Приховане переповнення обнуляє автоматичний мінімум flex-елемента, і в коробці зі сталою висотою підпис стискається до нуля. Виміряно на цьому ж кроці: 3px і слово, обрізане до смужки.
Стани, що є в коді

Атом має один стан, і рівно той, що належить йому: :hover знімає з підпису пришпильку. Усе інше дає той, хто контрол поставив - у шапці ґрунт і чорнило приходять з фінішу btn--ghost, у таб-барі активність каже [aria-current]. Стан «де ти є» знає організм, а не контрол.

Крок 7.20: під курсором рухалась половина контрола

Виміряно в шапці на 1280. У спокої ґрунт прозорий, мітка #1C1C1C, підпис #5B5B54. Під курсором btn--ghost підіймає теплий ґрунт і веде чорнило в акцент - а підпис лишався #5B5B54:

ґрунтміткапідпис
спокійпрозорий#1C1C1C#5B5B54
наведення до 7.20#FAF9F7#FF5A00#5B5B54 - не зрушив
наведення після#FAF9F7#FF5A00#FF5A00

Це не збиток зведення: .wfh-act.stack .lbl тримала колір і до 7.18, а таб-бар, чий підпис успадковував колір, ховера не має взагалі - тож ніде в продукті слово не рухалось разом зі своєю міткою.

Пришпилька правильна у спокої й хибна під курсором. Підпис під міткою - частина імені контрола, саме тому він тримається на --text-secondary, а не на muted; ім'я не може лишатись позаду, коли те, що воно називає, засвітилось. Тому inherit, а не названий колір: підпис бере те чорнило, яке вирішив фініш, і атому не треба знати, який фініш йому дали.

Де не відбувається нічого - теж правильно. У таб-бара фінішу немає й ховерного чорнила він не оголошує, тож inherit повертає колір спокою і вкладка не рухається. Це смуга телефона: ховер там - це стан, який жоден телефон не намалює. Активна вкладка під курсором тримає свій чорнильний підпис, бо .wf-tab[aria-current] .tl в'яже це правило за специфічністю і вантажиться пізніше.

Натиск і фокус крок 7.33

Розділ вище закінчується тим, що таббар не оголошує наведення, і що наведення там - стан, який жоден телефон не намалює. Обидва твердження правильні, і разом вони лишили власну навігацію телефона зовсім без відповіді. Зміряно на listing.html: .wf-tab у спокої, під :hover і під :active тричі повернув однаковий computed style. П'ять вкладок на 34 екранах - контрол, якого торкаються частіше за будь-який інший у цьому продукті, - не підтверджував, що до нього торкнулись.

Наведення правильно було відсутнє. Натиск - це той стан, який телефон малює, і саме його бракувало.

ЗмінаТаббарХедер
:active -> --bg-action-softновебез змін: там уже btn--ghost, чий :active дає ту саму землю
border-radius: --radius-8нове й видиме тільки під пальцембез змін: btn--ghost уже має цей кут
:focus-visible -> --ring-focus-controlнове, було rgb(0, 95, 204) auto 1pxбез змін

Радіус оголошено, а не підсунуто. Вкладка - п'ята частина екрана без власного кута, тож земля натиску лягла б прямокутником упритул до сусідів. --radius-8 - кут контрола цього набору. A/B на 108 994 елементах показав рівно 340 розбіжностей у спокої, і всі 340 - це він: 5 вкладок x 34 екрани x 2 в'юпорти.

Кільце зовнішнє, а не всередині: бар не ставить overflow, а вкладка досить широка, щоб внутрішнє кільце читалось як рамка навколо підпису.

Зміряно дотиком на 390 x 844: вкладка прозора -> #FFF9F5. Кільце на сусідній вкладці не зрізане нижнім краєм
Рух

Робота: ВІДПОВІДЬ. Рухається: color. Тривалість --dur-fast (150ms), крива --ease-standard. Значення читаються через var() з tokens.css: підміна токена в браузері веде за собою кожне з них, тобто числа у файлі немає. При prefers-reduced-motion рух зникає, а стан лишається.

Токени

Прочитані з stack-action.css, не переписані руками. Шість ролей на десять примітивів, і в цьому наборі два кільця фокусу - єдиний компонент системи, який читає обидва.

Семантичні ролі (6)Примітиви (10)
--bg-action --bg-action-soft--fs-10 --fs-12
--ring-focus-control--fw-semibold --fw-black --lh-flat
--ring-onink--radius-8 --radius-pill
--text-onaction-ink--size-20
--text-secondary--space-2 --space-4
–--dur-fast --ease-standard

Два кільця, бо той самий контрол стоїть на двох різних ґрунтах. На сторінці працює --ring-focus-control. На темній смузі шапки кільце тієї самої ролі зникло б у власному тлі, тож там працює --ring-onink - біле гало, викарбуване саме для цього випадку. Це і є той поділ за ПОВЕРХНЕЮ, який етап оголосив третьою віссю: роль каже не лише «яким кольором», а й «на чому».

Пари ґрунту рівно дві - --bg-action і --bg-action-soft, - і другий це ховер. Жодного власного токена стану компонент не заводить: усе, що йому було потрібно, семантичний рівень уже мав.

Холостий контроль

Сторінка звіряє себе з файлом: 9 власних класів і 1 стан оголошено в stack-action.css. Нижче - ті, яких на цій сторінці немає ні в демо, ні в розмітці.

Розмітка
<a class="btn--ghost btn--s btn--stack wfh-act stack" href="..."> <span class="g">♡<span class="hb">6</span></span> <span class="lbl">Обране</span> </a> <a class="btn--stack wf-tab" href="..." aria-current="page"> <span class="ti">♡<span class="tbadge">6</span></span> <span class="tl">Обране</span> </a>

Два словники частин - це борг, а не задум. Одне правило їх обслуговує, як .ci-qty, .co-qty у Лічильнику кількості; звести імена можна буде тоді ж, коли розморозиться сірий шар.

Де вживається

Якорі: .btn--stack

Шапка - «Увійти» / «Кабінет ▾» і «Обране», на кожному екрані від 1024. Таб-бар - п\'ять вкладок, на кожному екрані до 859. Обидва будує wireframes/_nav.js, тож у розмітці сторінок їх немає - рахувати треба в браузері.

Немає в коді -> етап 09

Чого бракує

  • Два словники частин - .g/.ti, .lbl/.tl, .hb/.tbadge. Правило вже одне, імена ще ні; перейменування чекає Кроку 6
  • Немає фокуса - у шапці кільце дає btn--ghost, у таб-барі немає нічого: вкладка, до якої дійшли клавіатурою, не відрізняється від сусідньої. Ховер атом закрив на кроці 7.20, фокус - ні, бо кільце малює фініш, а в таб-бара фініша немає
  • Дотик 44 не перевірено для вкладки - коробка 50 заввишки, але ширина це п\'ята частина екрана: на 320px це 64, а на вужчих не міряно

Не домальовано наперед і не замовчано: етап 09 стартує з цього списку, зведеного в design/kit/docs/architecture.md.