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

Чип

Пілюля зі словом, яку натискають, щоб обрати. Фільтр, категорія, вкладка, ціль - одна форма на всі чотири роботи.

рівень 1design/system/components/chip.css402 рядки8 імен6 файлів
Анатомія
наведіть - край іде в акцент і слово з ним; це один ховер на всі вісім імен, і .dr-chip отримав його щойно
1Пілюля - --radius-pill, край 1.5 --line-strong. Форма, яку читають як «натисни»
2Підпис - іменник, не дієслово: чип це вибір, а не дія. 14 / semibold у фільтра, 14 / bold у сегмента
3Лічильник .ct - скільки товарів дасть цей фільтр. 12 / --text-muted: тихіший за слово, яке рахує
4Мітка - лише там, де чип веде в ціль. У фільтра її немає: список фільтрів читають стовпчиком, і мітка щоразу відсувала б слово
Вісім імен у шести файлах малювали ту саму пілюлю

Це не здогад, а перепис у браузері: 17 кольорових екранів, 1280 і 390, кожен екземпляр зміряний через getComputedStyle.

КласСкількиФайл до 7.23Де
.dr-chip96chip.cssцілі в бічній шухляді
.flink60link-row.css -> сюди на 7.23опції фільтра, «Концентрат 31»
.flinks6link-row.css -> сюди на 7.30bряд цих опцій - лишився позаду на 7.23
.mgchip42header.cssкатегорії в мега-меню
.hero-chips a32chip.cssрейка категорій на телефоні
.ptab32pdp-tabs.cssвкладки добірок і товару
.acc-link28account-shell.cssтаби кабінету, пілюля лише від 860
.ord-tab6order-row.cssфільтр замовлень
.cegoals button6chip.cssціль у діалозі клієнта тренера

.acc-link не переїхав, і це навмисно: це рядок на всю ширину з волосиною під ним, який стає пілюлею лише від 860. Його форма - речення оболонки кабінету, а не цього файлу. Обраний стан у нього вже той, який тепер спільний, тож у ньому не змінилось нічого.

Що розійшлось - і що тепер сказано один раз
ВісьБулоСтало
Край1.5 скрізь, крім .ord-tab - там 11.5. Фільтр замовлень став 41 заввишки замість 40
Чорнило у спокої--text-body, крім .ord-tab - --text-secondary--text-body. Вибір, який ще не зроблено, не є приглушеним
Наведенняакцентний край + акцентне слово (.flink, .ptab, .hero-chips a) · чорнильний край + чорнильне слово (.ord-tab) · акцентний край + чорнильне слово (.mgchip) · жодного у .dr-chipОдна редакція - акцентний край і слово. Найбільша родина, 96 екземплярів, отримала ховер уперше
Вага і падінг600/12 і 700/16 уперемішДві сходинки, і вони справжні - див. нижче

Дві сходинки, а не чотири розміри

Фільтр - 14 / semibold / падінг 12. Він один із багатьох, його тиснуть у будь-якій комбінації, і в стовпчику з десяти опцій вага 700 перетворила б список на стіну.

Сегмент - 14 / bold / падінг 16. Це набір, де увімкнено рівно один: вкладка товару, фільтр замовлень, ціль клієнта. Перемикач важить більше за фільтр, і око має знайти поточний, не читаючи.

Мала сходинка - 12 / semibold / падінг 4, 29 замість 41. Лише мега-меню: колонка там щільна, і чипи стоять під заголовком, а не самі по собі.

Обраний: було чотири редакції, лишилась одна
ПопулярніНовинкиАкції
сегмент: увімкнено рівно один, і наведення на нього нічого не змінює - далі йому нема куди

Вибір зроблено за контрастом, а не за смаком. Виміряно на #FF5A00:

РедакціяСкількиКонтрастПрисуд
акцентна заливка + чорнильний підпис .acc-link285.45:1обрано - найбільша родина і єдина акцентна, що проходить AA
акцентна заливка + білий підпис .ptab.on83.13:1нижче AA для 14px
білий фон + акцентний край і підпис .ord-tab.on23.13:1нижче AA для 14px
чорнильна заливка + білий підпис .cegoals button.on615.9:1проходить, але акцент більше не позначає вибір

Три редакції приведено до першої. Це видима зміна на трьох екранах, не косметика: вкладки товару втратили білий підпис, фільтр замовлень - контурний вигляд, ціль у діалозі тренера - чорну заливку.

Родина в одному ряду
сегментУсіДоставленіВ дорозі
ціль у діалозі
рейка ≤859За ціллюПротеїнГейнери
застосованийБренд: Optimum NutritionСкинути все
рейку .hero-chips видно лише до 859 - вище вона display:none, тож звужте вікно, щоб побачити її живою

Застосований фільтр - інша робота, і тому він єдиний лишився зі своїм виглядом. Це не вибір, а квитанція: він каже, що фільтр уже увімкнено, і пропонує зняти його. Звідси тихіший розмір, підкладка замість білого і хрестик, якого немає більше ні в кого.

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

Від якого порогу: --bp-shell-wide (860). Що саме міняється: чипи цілей у геро ховаються. Чому це виняток: етап каже, що компонент міряє свій контейнер, а в'юпорт міряє лише оболонка. Це правило - один із двох названих винятків, і причина в тому, що ховаються вони не тому, що їхня коробка стала широкою, а тому, що від 860 на тому самому екрані видно плитки тих самих шести цілей. Це факт про те, що показує екран, і жоден контейнерний запит його не спитає. Виняток перелічений у responsive.md.
Коли вживати

Фільтр - у рейці й шиті фільтрів, у мега-меню, на рейці категорій телефона. Сегмент - там, де з набору увімкнено рівно один. Job 2, новачок: чип це найдешевший спосіб почати не з каталогу, а з наміру - одне слово замість форми.

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

Правило

Чип - це іменник. «Протеїн», «Набір маси». Дієслово в пілюлі читається як кнопка, і людина чекає, що після натискання щось станеться, а не що список звузиться.

Антиправило

Не роби з чипа Бейдж. Мітка, яку не можна натиснути, не має бути схожою на ту, яку можна. .acc-tier «Срібний рівень» і статус «Доставлено» - пілюлі, але вони нічого не роблять: це Статус-пілюля, і живе вона в іншому файлі.
Шар взаємодії крок 7.31

7.23 звів вигляд. Те, чого він не торкався, - чи можна цим користуватися. Переписано наново в браузері, 40 кольорових екранів × два в'юпорти: 503 екземпляри, і обидві сходинки тримаються без жодного відхилення. Розійшлось інше.

КласТегКлавіатура до 7.31Кільце фокуса до 7.31
.dr-chip .flink .mgchip .hero-chips a<a href>досяжні нативносинє кільце браузера
.afilter .x<button>досяжна, і вже названасинє кільце браузера
.ptab<span>недосяжні - а на клік відповідали-
.ord-tab<span>недосяжні - і на клік теж не відповідали-

Кільце малював браузер. Прохід по всіх завантажених таблицях стилів у пошуку outline або box-shadow на будь-якому з восьми імен повернув порожній список. Тобто кожен чип, до якого клавіатура доходила, показував outline: rgb(0, 95, 204) auto 1px - типовий контур Chrome, на сайті, де --ring-focus-control є з кроку 6.2 і його вже читають кнопка, поле, радіо і посилання. Чип був останнім контролом, що позичав кільце в браузера.

Сегмент отримав клавіатуру - uivSegments() у design/_nav.js: role="tablist" / role="tab" / aria-selected і мандрівний tabindex, точно як у радіо. Набір бере один крок табуляції, стрілки ходять усередині з перекотом, Home і End стрибають у краї. Три фільтри, кожен зі своїм кроком, коштували б більше, ніж дають.

Що знайшлось попутно

.ord-tab не відповідав і на мишу. Три фільтри над списком замовлень - «Усі · Доставлені · В дорозі» - нічого не робили при кліку. Зміряно, не припущено: клік по індексу 2 лишав .on там, де він був. Тобто це був не дефект клавіатури, а мертвий контрол.

І розмітка це вже обіцяла

account-orders.html уже писав role="tablist" aria-label="Фільтр замовлень". Сірий шар оголосив набір вкладок і не з'єднав жодної. Тому це не вигадана поведінка, а виконання того, що розмітка обіцяла роками.

role="tablist", а не radiogroup: радіо обирає значення, яке піде в замовлення, вкладка перемикає, який зріз того самого списку ви бачите. Механіка та сама, обіцянка різна - і межа між ними та сама, яку chip.css проводить між фільтром і сегментом.

Стани, що є в коді

Три: :hover, :focus-visible і .on. Перші два в одній редакції на всі вісім імен; третій тримається на класі, тому він у списку класів, а не станів.

НаведітьПройдіть TabОбраний
Tab по цій сторінці показує кільце --ring-focus-control - те саме, що в кнопки, поля, радіо й посилання. Миша його не запалює: правило стоїть на :focus-visible, а не на :focus

Стану «недоступний» немає, і це відповідь, а не прогалина. У продукті нуль чипів із disabled, .off чи .disabled - на жодному з 40 екранів, у жодному в'юпорті. Раніший запис «скопіювати .vopt.off» відкликано: .vopt.off існує тому, що смак справді буває розпроданий, а фільтр, який дасть нуль товарів, - випадок, якого в продукті поки немає. Намалювати його тут означало б вигадати стан. З'явиться випадок - форма для копіювання вже є.

Натиск крок 7.33

7.31 дав чипу кільце фокуса. Те, чого він не торкався, - відповідь на палець. :hover вище рухає край і слово, і це правильна відповідь курсору й ніяка відповідь пальцю: жоден із двох станів ніколи не спрацює на пристрої, під який цей продукт зроблено першим. Чип - найчисленніший контрол сайту, 503 екземпляри, і до цього кроку він був також найчисленнішим контролом, що на натиск не відповідав нічим.

ЩоУ спокоїПід пальцемЗвідки значення
звичайний чип#FFFFFF#FFF9F5--bg-action-soft, те саме, що в .btn--outline:active
обраний чип .on#FF5A00#E85200--bg-action-pressed, те саме, що в .btn--accent:active

Натиск - не те саме питання, що наведення. Обраний чип навмисно не перефарбовується під курсором: акценту нема куди йти по акценту, і це читалось би як завантаження. У натиску є куди - на сходинку темніше. Без цього обраний чип був би єдиним мовчазним у сімействі, а це саме той, по якому тиснуть двічі: фільтр, який вимикають.

Зміряно справжнім дотиком у touch-контексті 390 x 844: .flink #FFFFFF -> #FFF9F5, .ptab (це <span>) #FFFFFF -> #FFF9F5, .ptab.on #FF5A00 -> #E85200. Не примусовий стан у DevTools, а тап
Публічний ряд і чотири форми чипа -> 12.4, 12.9

До партії 2 цей файл мав ТРИ приватні імені для ряду чипів - .dr-chips, .cegoals, .flinks - кожне у власності одного місця. Четверте приватне ім'я було б тим самим рядком, написаним учетверте, тож ряд став публічним: .chips.

.chips--center - та сама анатомія, змінена лише вісь. Ряд відновлення під центрованим блоком помилки: злівавирівняний ряд там читається як список, що загубив заголовок.

.chip--letter - літера покажчика А-Я, з мінімальною шириною, щоб двадцять шість літер стояли колоною. .chip.off - літера, за якою немає жодного бренду: файл сам записав цей випадок ще на етапі 08 («вимкненого чипа в продукті НЕМАЄ... коли випадок з'явиться, .vopt.off - та форма, яку копіювати»), і на brands чотирнадцять із двадцяти шести літер порожні.

.chip--fill - залитий ґрунт замість обведення, коли ряд стоїть на сторінці, а не в панелі. .chips--sticky - ряд, що липне під шапкою на довгій сторінці; ховає власну смугу гортання і не дає дітям стискатись.

Той самий ряд липким. Липкість видно лише на довгій сторінці - тут показано, що клас несе ряд, а не як він поводиться при гортанні:
Рух

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

Токени

Прочитані з chip.css, не переписані руками. Чотирнадцять ролей на десять примітивів - єдиний атом системи, де ролей більше, ніж примітивів, і причина проста: чип це найповніший набір станів у системі. Сім із чотирнадцяти ролей існують лише заради взаємодії.

Семантичні ролі (14)Примітиви (13)
--bg-action --bg-action-pressed --bg-action-soft --bg-page --bg-sunken --line-action --line-hair --line-strong --ring-focus-control --text-action --text-body --text-muted --text-onaction-ink --text-primary--dur-fast --ease-standard --fs-12 --fs-14 --fw-black --fw-bold --fw-semibold --radius-pill --size-32 --space-12 --space-16 --space-4 --space-8

--bg-action-pressed - це роль, яку завів натиск, і завела саме тому, що ховер уже витратив --bg-action-soft: коли обраний чип уже стоїть на помаранчевій заливці, посвітліти йому нема куди, тож натиск іде на крок ТЕМНІШЕ. Чотири стани, чотири ґрунти, жодного нового hex.

--text-onaction-ink існує через поверхню, а не через колір. Це чорнило НА дії, і поріг йому потрібен текстовий - 4.5:1, - а не той, за яким рахують заливку. Роль, оголошена як заливка й поставлена під дрібний жирний підпис, проходить перевірку поверхні й провалює текстову, і таблиця пар «текст/фон» цього не бачить, бо текстовою її ніхто не оголошував.

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

Сторінка звіряє себе з файлом: 16 власних класів і 2 псевдостани оголошено в chip.css. Обраний тримається на класі .on, тому він у списку класів, а не станів. Нижче - те, чого на цій сторінці немає ні в демо, ні в розмітці.

Розмітка
<span class="chip">Протеїн</span> <a class="flink">Концентрат<span class="ct">31</span></a> <span class="ptab on">Популярні</span> <!-- сегмент: увімкнено один --> <span class="afilter">Бренд: Optimum Nutrition <button class="x" aria-label="Прибрати фільтр">✕</button></span>

Імена не перейменовано: .dr-chip, .mgchip і .cegoals пише wireframes/_nav.js, який виконує й заморожений сірий шар. Додати chip у список селекторів безпечно в обидва боки, перейменувати - ні. Перейменування - пункт Кроку 6, як і в Лічильника кількості та Дії стовпчиком.

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

Якорі: .chip .dr-chip .flink .flinks .mgchip .hero-chips .ptab .ord-tab .cegoals .afilter

Каталог і лістинг, картка товару, кабінет і замовлення, головна, мега-меню, бічна шухляда, діалог клієнта тренера. .cegoals сьогодні рендериться лише в сірому шарі - тренерських екранів у design/ ще немає, тож перевірити його можна тільки тут, на стенді.

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

Три з чотирьох пунктів цього списку закрито на 7.31

  • З клавіатури недосяжні - .ptab і .ord-tab ходять стрілками, беруть один крок табуляції на набір і оголошуються як вкладки. Виявилось не потрібним переписувати розмітку: role і tabindex ставить uivSegments() на рендері, як 7.29 зробив для радіо
  • Немає фокуса - --ring-focus-control на :focus-visible, на всі вісім імен і на хрестик застосованого фільтра
  • Немає стану «вимкнено» - відкликано. У продукті нуль недоступних чипів; малювати стан під випадок, якого немає, означало б вигадати його

Чого бракує

  • Одне ім'я замість восьми - правило вже одне, імена ще ні. Перейменування ламає заморожений сірий шар, тому це Крок 6, після етапу 09
  • .acc-link тримає край 1px, коли вся родина тримає 1.5 - і вище 860 це та сама пілюля сегмента з тими самими 14/700/8-16. Різниця в один піксель дає 40 замість 41. 7.23 вивів .acc-link із родини свідомо, тому це не правиться мовчки: рішення чиєсь, не моє
  • Немає :active - жоден чип не показує момент натискання

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