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

Перевірка тренера

Вузол 5.1: покупець стає тренером. Роль активується поверх наявного акаунта, і між заявкою та гуртовою ціною стоїть людська перевірка - за посиланням на профіль. П'ять екранів одного потоку в одному файлі, і спільного в них рівно один об'єкт.

рівень 3design/system/components/coach-verify.css972 рядки72 селектори261 оголошення5 екранів
Один хребет, п'ять тіл

Файл виглядає як п'ять екранів, зшитих разом, але замір каже точніше. Кожен клас звірено з розміткою всіх п'яти кольорових екранів:

Скільки екранівКласиЩо це означає
5 з 5.cv-wrap .cv-steps .cv-step (+.n b .on .done .stop)Хребет. Тримісний маркер прогресу - єдине, що бачать усі п'ять
3.cv-card .cv-altкартка стану і рядок «передумали»
2.cv-badge .cv-actionsзначок результату і ряд дій під ним
1.cv-split .cv-body .cv-aside .opt-tiles .city-chip .cv-consent .fhint .cv-ring .cv-steps2 .cv-btnrow .cv-note .cv-reasons .cv-sub .cv-h1 .cv-ok .cv-footШістнадцять класів живуть на одному екрані кожен. Це не марнотратство: стан має право виглядати як стан

Саме тому це один файл, а не п'ять. Хребет був би скопійований п'ять разів, і він уже був: до кроку 7.23 вісім правил маркера стояли байт у байт у п'яти приватних блоках. Заміряно на 1280 у ту мить, коли їх видаляли:

ЕкранПлиткаКрайЦифраПідпис
coach-verify65.591px12px14px
інші чотири65.471.5px11px12.5px
Одна річ, п'ять редакцій, і розійшлись вони на чверть пікселя, півпікселя краю і півтора пікселя тексту - тобто рівно настільки, щоб ніхто не помітив
Маркер прогресу знімає скоуп .coach, і це не недогляд

Усі 67 селекторів файлу починаються з .coach - крім восьми правил маркера. .cv-step трапляється рівно в шести файлах: п'ять екранів цього потоку і цей. Ім'я вже і є скоуп, а зайвий .coach означав лише «той єдиний екран, який здогадався так сказати».

Альтернативи були обидві гірші. Повернути копії на чотири сторінки - це той самий дефект, виписаний ще чотири рази. Поставити coach на їхній <body> - це віддати їм весь файл, а .cv-card означає різні речі на різних екранах. У сірому прототипі всі п'ять і досі мають голий <body>; у кольорі всі п'ять несуть class="coach", тож сьогодні хребет дістає їх обома шляхами - і саме тому знятий скоуп нічого не ламає, а копії не повертаються.

Анатомія

Розмітку знято з п'яти кольорових екранів у цій сесії через tools/demo.mjs, разом із класом coach на <body>. Хлібні крихти зняті - це breadcrumb.css. Рамки на 860, бо стільки дає .cv-wrap: це ширина читання двоколонкової картки, а не межа.

Крок 1. Єдиний з п'яти екранів із формою, і єдиний, де маркер стоїть на .on без жодного .done перед ним
1Маркер .cv-steps / .cv-step - flex: 1, мінімум 92px, чотири стани: спокій · .on поточний · .done пройдений · .stop зупинений
2Розкол .cv-split - одна колонка, від 760 дві. Ліва .cv-aside бере 38%, і це частка, а не довжина; діалог входу дає своїй половині 44%
3Панель довіри .cv-aside - три причини, чому тренер узагалі заповнює форму. --bg-surface, і штрихування звідси прибрано: --bg-hatch у системі означає «картинки ще немає», а це не відсутня картинка
4Форма .cv-body - поле, місто, тип, посилання, згода. Жоден контрол у ній не належить цьому файлу
5Плитки типу .opt-tiles - тільки сітка. Саму плитку малює radio.css, і вибраний стан бере ту саму дію, що й маркер
Крок 2. .cv-ring - кільце очікування · .cv-steps2 - другий, дрібніший список кроків усередині картки, з .now на поточному. Два списки кроків на одному екрані, і це названо нижче
.cv-badge.bad і .cv-reasons - значок відмови й список причин. Картка не .mid: текст ліворуч, бо його читають, а не сприймають
.cv-step.stop - четвертий стан маркера, і єдиний, який каже, що далі шляху немає. Картка .mid, тобто по центру
Крок 3. .cv-ok - підтвердження, .cv-h1 - заголовок поза карткою і поза .cv-body, .cv-foot - дрібний рядок під вибором. Самі тарифи малює plan-card.css
Знайдено на цій сторінці: бренд у двох редакціях

Панель довіри починається зі слова Stack у класі .vlogo. Це ім'я діалогу входу: auth-dialog.css малює .auth-visual .vlogo, і файл сам це визнає - «ця панель це візуальна половина діалогу входу, побудована вдруге». Але однакове ім'я малює дві різні речі. Заміряно обчисленим стилем:

ДеШрифтРозмірТрекінгЗнак брендуКоробка
.auth-visual .vlogo - діалог входуOswald24px-0.48pxє, ::before з logo-mark.svg356 x 42
.cv-aside .vlogo - ця панельInter20px-0.4pxнемає269 x 32

І правило само каже, який шрифт мало на увазі. Воно оголошує letter-spacing: var(--ls-display) - трекінг дисплейного накреслення - і не оголошує font-family. Це рівно та сама форма, що й H1 на лендингу тренера: токен трекінгу називає накреслення, якого декларація не попросила.

Питання ширше за цей компонент, тож зміряно по всьому кольоровому корпусу. --ls-display читають десять правил, і рендеряться вони так:

НакресленняСкількиЯкі
Oswald, дисплейне4.auth-visual .vlogo 24 · .co-logo 20 · .wfh-logo 20 · .lh1 30
IBM Plex Mono2.bb .new 36 · .coachbox .cbnew 30 - це гроші, і моно тут за правилом ціни
Inter, шрифт інтерфейсу4.cv-aside .vlogo 20 · .wff-col a.wff-phone 24 · .sys-min .sys-logo 24 · .sys-code 60

Логотип-слово має п'ять редакцій, і дві з них без знака

Три несуть знак і дисплейне накреслення - хедер, чекаут, діалог входу; logo-mark.svg малюється з чотирьох різних файлів компонентів. Дві не несуть нічого: сторінка 404 і ця панель. Тобто на екрані, де тренер вирішує, чи довіряти магазину свої дані, бренд стоїть у шрифті інтерфейсу без знака - а на екрані входу той самий клас стоїть у фірмовому.
Не правлено тут, і не тому, що дрібниця: логотип - це значення, у нього п'ять місць у чотирьох файлах, і звести їх означає завести компонент, якого система не має. brand-logo.css - це не він, а ряд логотипів виробників у каталозі. Етап 09.
560 стала шириною картки, і це остання приватна правка продукту

До кроку 8.48 два з п'яти екранів несли у власному <style> одне й те саме правило, байт у байт: .cv-card{ max-width: 560px; margin: 0 auto }. Крок 8.40 відклав його чесними словами - «чи стане 560 шириною панелі, вирішує етап 09» - і не сказав головного: третій екран уже возив іншу відповідь.

ЕкранКласБуло на 1280Текст
coach-verify-error.cv-card560ліворуч
coach-verify-deadend.cv-card.mid560по центру
coach-verify-loading.cv-card.mid828по центру, коробка H1 778

Закрити це без рішення було неможливо, і саме тому воно так довго стояло: немає селектора, який відділив би два екрани, що правило оголосили, від третього, що ні. Рішення сказано вголос - змінна: .coach .cv-card отримує max-width · значення: 560px · чому: три причини нижче.

Чому 560

1. Два з трьох оголошують це правило однаково. Правило, яке два екрани пишуть однаково, - не вибір екрана, а правило компонента, що стоїть не в тому файлі.
2. Система вже звужує те, що всередині картки: .cv-lead 440, .cv-card.mid .cv-actions 340. Ширина самої картки - це та сама заява, яку ці два обмеження вже наполовину зробили.
3. .mid означає «по центру», а 828 завелика, щоб у ній центрувати. Екран очікування центрував заголовок по коробці 778, поки два його сусіди центрували той самий ранг по 510.

Що це коштує, зміряно A/B у живій сторінці

error і deadend - однакові до байта на 1280, 900 і 390. Кожне число. Тобто для них це чистий переїзд.
loading на 1280 і 900: картка 828 → 560, ряд кнопок з одного рядка у два, висота 571 → 623. Дві з тих трьох кнопок - демо-перемикачі прототипу («Далі (демо: перевірку пройдено)», «Демо: не пройдено»), а не контроли продукту.
loading на 390 - однаковий до байта: обмеження там ніколи не спрацьовує.
scrollWidth - clientWidth нуль скрізь, до і після.
Скасовується одним оголошенням, якщо власник читає інакше. Уся ціна помилки тут - 268px на одному десктопному екрані. Після цього кроку в продукті нуль приватних правил: 886 → 3 → 2 → 0
Що цей файл віддав, і що взяв назад

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

Що було локальнимКому відданоЩо з цього вийшло
.fld, .fld > labelfield.cssЛітеральний випадок: обидва селектори вже оголошені в field.css, а .fld > label був байт у байт рядком із wireframes/_wf.css. Екран перенабирав глобальне правило
.txt-field, .txt-field:focusfield.cssКоробка, яку малював екран - край 1.5px, радіус 10, поля 13/12, тип 15, чорнильний контур 2px на фокусі - одна з дев'яти висот і п'яти розмірів, заради яких переписували поле. .txt-field це не контрол, а позиція
.city-chip - кнопка вибору містаbutton.cssДруга редакція кнопки. Лишився один селектор, .city-chip .ch - назва міста всередині
.cv-ctabutton.cssПервинна дія, побудована руками. Розмітка носить btn--accent btn--l btn--full cv-cta, тобто три класи кнопки вже стоять поруч
плитка типу тренераradio.cssТут лишилась тільки сітка .opt-tiles

А назад узято заголовок. Дві прийняті сторінки тієї самої форми - .co-h1 в чекауті й .auth-h1 у діалозі входу - пишуть однакові п'ять оголошень. Ця форма писала шосте. Заміряно до правки: Inter 700 24px, трекінг -0.24px, коробка 312 x 38.4 на 390 - єдиний заголовок сторінки в кольоровому продукті, що лишався в тілесному шрифті. Стало Oswald 600 30px.

І це третій потік, знайдений у двох накресленнях для одного рангу: перший записав coach-clients.css («один кабінет носив ЧОТИРИ трактування заголовка»), другий - coach-cabinet.css. Тут база малювала Oswald 30/600 усередині .cv-body, а три екрани стану - Inter 22/800 усередині .cv-card, зі своїх приватних блоків. Один потік, один ранг, один слот, два накреслення й вісім пікселів різниці.

Селектор тому й потрійний: .cv-body h1, .cv-card h1, .cv-h1. Третє ім'я додано на 8.40, коли знайшлось, що заголовок екрана тарифу не лежить у жодному з двох
Типографіка: дев'ять розмірів, знятих чужим рішенням

Те саме правило, що й на лендингу тренера, і воно ж належить власникові: крок 5.5 знімає півпікселі таблицею (нічия йде до більш читаного сусіда), крок 5.6 підіймає цілі до дев'яти щаблів.

КласСірийСталоЯке правило
.cv-step .n11--fs-125.6, нічия вгору
.fhint11.5--fs-125.5 → 12, і 12 це щабель
.cv-step b12.5--fs-145.5 → 13, далі 5.6 вгору
.cv-aside li12.5--fs-14те саме
.cv-alt12.5--fs-14те саме
.cv-aside .vtag13--fs-145.6, нічия вгору
.cv-lead13.5--fs-145.5 → 13, далі 5.6 вгору
.cv-aside .vtag b14.5--fs-145.5 → 14, і 14 це щабель
.city-chip1516оголошення пішло: button.css дає 16 і без цього

Той, що пішов ВНИЗ, - це правило, а не виняток

.cv-aside .vtag b з 14.5 у 14 колись читали як доказ, що «замітання йшло не тільки вгору, а двобічне округлення - це недогляд». Обидві половини хибні: 14.5 → 14 це шостий рядок таблиці 5.5, нічия до більш читаного сусіда, а 14 уже щабель, тож 5.6 його не чіпає. Продукт узяв те саме 14.5 → 14 утретє в buy-box.css, у файлі поза цією партією.

Геометрія лишилась уся, і це правильна асиметрія

20 позначок [?] у файлі. 92, 10, 9, 22, 6, 20 і 7 - усе ще літерали, бо відступи мають два правила, що суперечать одне одному (5.5 нічия вгору, 7.67 округляй униз), а радіус бере нічию вниз. Типографіка - єдина з трьох драбин з однозначною записаною відповіддю.
Коли вживати

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

Практичне: маркер прогресу з цього файлу - єдине, що можна позичити, і позичати його поки нікуди. .cv-step зустрічається в шести файлах, і всі шість - цей потік. Коли з'явиться другий багатокроковий процес, це буде рівно та мить, коли маркер стане молекулою і поїде звідси у свій файл.

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

Правило

Стан має право на власний вигляд, ранг - ні. Шістнадцять класів живуть на одному екрані кожен, і це нормально: кільце очікування нема де вживати вдруге. Але заголовок сторінки - це ранг, і він однаковий на всіх п'яти; саме тому селектор заголовка потрійний, а не п'ятиразовий.

Антиправило

Не переписуй хребет у стан. Копія маркера в приватному блоці екрана виглядає безпечно рівно доти, доки їх не стане п'ять і вони не розійдуться на півпікселя. Якщо стану треба інший маркер - це новий стан маркера (.stop), а не нова редакція маркера.
Обмеження

Правила вживання, які називають саме цей компонент: U9. Автор правил один, і це architecture.html, розділ I; тут - витяг.

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

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

У файлі нуль :hover, нуль :active і нуль :focus-visible. Усе, що відповідає на палець, - це .btn, поле, радіо або чекбокс, і за них відповідають їхні атоми.

Стани тут класи, а не псевдокласи, бо це стани процесу, а не взаємодії - їх ставить сервер, а не курсор:

КласЩо кажеЧим малює
.cv-step.onви тут--line-action на краю, диск --bg-action з --text-onaction
.cv-step.doneпройденодиск гасне, всередину стає галочка
.cv-step.stopдалі шляху немає--line-danger, --text-danger
.cv-badge.badне підтвердилизначок у небезпечній ролі замість успішної
.cv-steps2 li.nowоце робиться заразтой самий --bg-action, на пів розміру менший
Поточний крок переїхав на колір дії на 7.96. До того найгучнішим об'єктом над згином був маркер прогресу, а єдина дія екрана стояла на 1545.7px нижче на 390: екран показував, де ви, замість того що робити
Межі

Дві, і після етапу 10 обидві з реєстру. До нього обидві були власні.

УмоваЩо змінює
(min-width: 860px)розкол стає двоколонковим, панель довіри бере 38% і міняє нижню рамку на праву, поля форми ростуть з 22 до 30/34. Було 760 - етап 10, раунд 3
(min-width: 620px)ряд дій під карткою перестає бути стовпчиком. Було 520 - етап 10, раунд 3
Холостий контроль

Сторінка звіряє себе з файлом: 35 класів і 0 станів оголошено в coach-verify.css. .coach не рахується - це скоуп. .uiv-ic теж - це icon.css, і тут компонент лише стоїть усередині нього.

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

Від яких порогів: --bp-shell-wide і --bp-grid-2col. Що саме міняється: від широкої точки екран верифікації стає двома панелями; від вузької плитки опцій стають трьома. Було 760 і 520, обидва поза реєстром. Яку з двох брати - зміряно, а не вибрано: примусовий ряд на 620 робить бічну панель 222.7 і обрізає плитки (324 у 319), а на 860 виходить 313.9 + 512.1 чисто. Плитки ж ідуть у зворотний бік: на 620 вони по 174.7 і не обрізають нічого проти 141.3 на 520 сьогодні.
Токени

Прочитані з coach-verify.css, не переписані руками. Жодного сирого кольору, хоча колірної половини у цих двох екранів ніколи не було: сірі імена перекладено за роботою, яку кожне з них виконувало в wireframes/_wf.css.

Семантичні ролі (18)Примітиви (27)
--bg-action --bg-page--container-text --font-display
--bg-success-soft --bg-sunken--fs-12 --fs-14 --fs-16
--bg-surface--fs-18 --fs-20 --fs-24 --fs-30
--line-action --line-danger--fw-semibold --fw-bold --fw-black
--line-hair --line-strong--ls-display --ls-lead
--line-success --line-success-soft--radius-8 --radius-12 --radius-16
--text-body --text-danger--radius-circle
--text-muted --text-onaction--size-46 --size-52
--text-primary --text-secondary--space-2 --space-4 --space-8 --space-12
--text-success--space-16 --space-24 --space-32

Один рядок таблиці перекладу більше не тримає. Сіре --dark означало «вибране / первинне» одним значенням, а кольоровий продукт розділяє ці дві роботи. Де воно означало ПЕРВИННЕ - це й досі інверсна пара; де ВИБРАНЕ, тобто .cv-step.on і його диск, - це тепер --bg-action / --line-action, ті самі токени, що читає .btn--accent. Питання закрили до цього файлу два інші: radio.css і chip.css.

Так само --strong розійшлось надвоє навмисно: --text-primary там, де рядок це заголовок, --text-body там, де це текст або посилання. Сьогодні однакове значення, дві роботи, і вони можуть розійтися пізніше
Розмітка
<main class="wf-page cv-wrap"> <div class="cv-steps" aria-label="Кроки"> <div class="cv-step on"><span class="n">1</span>Крок 1<b>Заявка</b></div> <div class="cv-step"><span class="n">2</span>Крок 2<b>Перевірка</b></div> <div class="cv-step"><span class="n">3</span>Крок 3<b>Тариф</b></div> </div> <div class="cv-split"> <aside class="cv-aside" aria-label="Навіщо це"> <div class="vlogo">Stack</div> <div class="vtag"><b>…</b>…</div> <ul><li><span class="m">✓</span> …</li>…</ul> </aside> <div class="cv-body"> <h1>Стати тренером</h1> <p class="cv-lead">…</p> <div class="fld"><label>…</label><input class="field txt-field"></div> <div class="fhint">…</div> <div class="opt-tiles" role="radiogroup">…</div> <label class="cv-consent">…</label> <div class="cv-alt">Передумали? <a>…</a></div> </div> </div> </main>

Галочка перед перевагою - набраний гліф у розмітці, <span class="m">✓</span>. Це та сама редакція, яку checkbox.css на кроці 7.38 замінив мальованою: набраний знак читається вголос, не має товщини штриха і стає туди, куди його поставить шрифт. Розмітка заморожена, тож це названо, а не змінено.

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

Якорі: .cv-wrap .cv-steps .cv-step .cv-card .cv-aside

5 кольорових екранів: coach-verify · -loading · -error · -deadend · -tier. Плюс секція 2 файлу - дельти тренера на шухляді кошика (cart-coach), які не заробили власного файлу: після видалення дублікатів і атомів від них лишилось одне правило, і воно названо бездомним у самому файлі.

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

Чого бракує

  • Панель довіри стоїть першою в DOM - на телефоні H1 «Стати тренером» починається на 716.8px згори, однаково на 390 і на 360, тобто нижче згину на обох. Переставити її або згорнути - це рух аргументу довіри, на якому екран побудований. Рішення власника
  • Логотип-слово в двох редакціях - див. вище. П'ять місць, чотири файли, немає компонента
  • Два списки кроків на екрані очікування - .cv-steps угорі й .cv-steps2 усередині картки. Другий детальніший, але це той самий процес, названий двічі
  • 38% проти 44% - цей файл дає боковій панелі 38%, діалог входу своїй 44%. Дві пропорції, і жодна ніде не записана як рішення
  • .cv-card має 40px поля в одному місці - 40 є щаблем, тож це вибір про той екран, а не дрейф, і скасувати його можна лише рішенням
  • max-width: 900px на екрані тарифу проти 860 на чотирьох інших. 900 - це число, яке крок 7.70 уже згорнув до 860 в checkout-form.css. Рядок того екрана, не цього
  • Набрана галочка в панелі довіри, при мальованій у чекбоксі. Розмітка заморожена, Крок 6

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