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

Клієнти тренера

Вузол 5.3 - збережений список людей, і вузол 5.4 - картка однієї з них. Це серце locked-рішення «тренер як покупець»: без цього списку тренерський канал не існує. Два екрани в одному файлі, бо три з чотирьох частин у них однакові й лише різного розміру.

рівень 3design/system/components/coach-clients.css908 рядків81 селектор262 оголошення13 екранів
Список і картка - одна людина двічі

Файл тримає дві половини, і вони не випадкові сусіди. .ccard - це підсумок людини в списку, .ch-* - та сама людина, відкрита. Аватар, ім'я і чип цілі є в обох, просто різного розміру:

ЧастинаУ списку (5.3)У картці (5.4)
аватар.ccard-av - 40.ch-av - 56
ім'я.ccard-nm.ch-name - те саме правило, що й .cl-h1: заголовок сторінки
чип цілі.ccard-goal - 12px.ch-goal - 12px, рамка --line-inverse
дії.ccard-acts - «Профіль» і «Нова сесія».ch-edit - «Редагувати клієнта»

Їх тримають разом на одну причину: наступний, хто змінить чип цілі, змінить його один раз. Розділені по файлах, вони розійшлись би так само, як розійшлись п'ять редакцій маркера в coach-verify.

Анатомія

Розмітку знято з кольорових екранів через tools/demo.mjs, разом із класом coach на <body>. Список показано на 732 - ширина колонки кабінету на 1280; картка на 860, бо вона живе не в кабінеті, а на власній сторінці.

Вузол 5.3: .cl-top з .cl-h1, .cl-sub, .cl-acts · .cl-tools з .cl-search · .clist у дві колонки від 620, а від 860 - у рейку поруч із клієнтом
1Шапка .cl-top - заголовок і дія в один ряд, що переноситься. .cl-h1 ділить правило з .ch-name: одне ім'я для заголовка сторінки на обох екранах
2Пошук .cl-search - зібраний руками field-grp, до якого атом не дотягується: розмітка не носить його класів. Коробка вже на щаблі атома, але група - ні
3Сітка .clist - одна колонка, від 620 дві, а від --bp-shell-wide одна знову, бо там вона стоїть рейкою в лівій колонці спліта. Картка .ccard ділить рамку, радіус і тінь із .ocard і .cdetails: один фініш для збереженого запису
4Мета-рядок .ccard-meta з .dot - «8 замовлень · останнє 12 черв. 2026». Крапка тут намальована, а не набрана: accept.mjs ловить набрані двійники окремою перевіркою
5Чип цілі .ccard-goal - дев'яте ім'я чипа, і мітка з підписом стоять на одній центральній лінії з кроку 8.8
Стан «досягнуто ліміту Free»: панель upsell.css над списком і .cl-sech - єдиний eyebrow цього файлу, який відділяє список від панелі. Сам ліміт - [?], і на екрані він так і написаний
Вузол 5.4: .ch з .ch-id, .ch-av, .ch-name, .ch-goal, .ch-edit · .cc-note · .cdetails з .cd-h, .cd-list, .cd-row · .cc-cta · .oh-h і .ohist з .ocard
Той самий клієнт без жодного замовлення. Порожній стан малює empty-state.css - цей файл віддає йому місце й не малює нічого
Знайдено на цій сторінці: .coach не є скоупом для двох тренерських файлів

Цей файл оголошує .coach .ch - рядок шапки картки клієнта, флекс-контейнер. Ім'я .ch оголошують ще два файли, і всі три означають різне:

СелекторФайлЩо цеДе
.coach .chцейрядок шапки картки: флекс, space-between, gap: 14px4 екрани клієнта
.coach .city-chip .chcoach-verify.cssназва міста всередині кнопки виборуcoach-verify
.co-saved .chcheckout-form.cssпосилання «· змінити» біля збереженої адресиcheckout-loggedin

Чекаут захищений: він поза .coach. А ось coach-verify - ні, бо він теж усередині .coach. Тож чотири оголошення цього файлу справді долітають до підпису кнопки міста: align-items, justify-content, gap і flex-wrap - ті, яких .coach .city-chip .ch не скидає.

Сьогодні це коштує нуль пікселів, і це зміряно

A/B у живій сторінці, чотири оголошення знято й повернуто, на 1280 / 900 / 390 / 360: підпис 67.16 x 15.61 на тій самій координаті, кнопка 444.13 x 52.00 (312.00 і 282.00 на телефоні) - геометрія ідентична на всіх чотирьох ширинах. Повний обхід дерева обчислених стилів: зрушив один рядок із 4 023, і це сам підпис із чотирма властивостями, які я й знімав.

Але рятує його випадковість, а не задум

gap, justify-content і align-items не діють ні на що, крім флекс- і грід-контейнера, а підпис - display: block: display: inline, оголошений у coach-verify.css, блокифікується флекс-батьком. Тобто два незалежні збіги. Наступне спільне ім'я між двома тренерськими файлами - підкидання монети, і це той самий рядок, що вже стоїть у coach-cabinet.css про простір імен co-.
Не правлено: перейменування - Крок 6, а вибір, кому лишити коротке ім'я .ch, - рішення власника
Що цей файл віддав, і чого він не скопіював

Найбільша одинична економія в усій партії 7.95 - і вона в тому, чого тут немає.

Оболонка кабінету - не цього файлу: 19 блоків оголошень на 16 селекторах видалено, а не скопійовано

.acc · .acc-nav · .acc-prof і три його дитини · .acc-tier · .acc-links · .acc-link і шість його форм разом із запитом на 960 · .acc-link.logout - усе це account-shell.css, який тримає їх повністю і в кольорі.

Власний коментар екрана казав це вголос: «Shell (acc / acc-nav / accard) mirrors account.html, coach mode» - і потім віддзеркалював його перенабором. Дзеркало, набране руками, - це копія, а копія розходиться. Три оголошення вже встигли.
Що було локальнимКому віддано
.oc-status - статус замовленняstatus-pill.css
рядок ціни в картці замовлення, 3 правилаprice.css - і це вже вдруге в цьому потоці
.ccard-acts .btnbutton.css. Тут лишилось одне flex: 1 - як контрол стоїть у ряду, а не який він
порожній стан картки клієнтаempty-state.css

А одне лишилось і назване чесно. .ch-edit - «Редагувати клієнта» - це <a> з краєм, радіусом, полями і nowrap, тобто btn--outline, виписаний руками: рівно те, заради чого кнопку переписували на 6.7. Правило стоїть, бо розмітка заморожена і не носить класу btn, тож видалення лишило б голе посилання. Поставити btn btn--outline btn--s на той якір - Крок 6, і він видаляє це правило одним рухом.

Типографіка: чотирнадцять

Те саме правило власника у два ходи, що й у решті партії. Чотирнадцять із чотирнадцяти, і 7.98 не поправив жодного.

КласЕкранСірийСталоПравило
.ccard-goalсписок11125.6, нічия вгору
.ccard-metaсписок12.5145.5 → 13, 5.6 вгору
.ch-editкартка12.514те саме
.cc-noteкартка12.514те саме
.oh-hкартка15165.6, нічия вгору
.oc-noкартка14.5145.5 → 14, і 14 це щабель
.oc-metaкартка12.5145.5 → 13, 5.6 вгору
.oc-statusкартка11125.6 (тепер status-pill.css)
.oc-nmкартка13145.6, нічия вгору
.oc-qtyкартка11.5125.5 → 12, і 12 це щабель
.oc-sumкартка13145.6, нічия вгору
.cd-hкартка1312вирішено деінде: заголовок узяв eyebrow кабінету
.cd-row dtкартка12.5145.5 → 13, 5.6 вгору
.cd-row ddкартка13.514те саме

Що знято при перевірці, і записано власними словами, щоб не повернулось

Цей блок колись перевіряв ті самі чотирнадцять проти «найближчий щабель, нічия вниз» і повідомляв, що 11 із 14 поїдуть назад, п'ять із них «перескочивши ближчий щабель». Дві помилки в одному реченні. Напрям для ТИПУ - вгору, а не вниз; вниз - це правило РАДІУСА, і вони протилежні навмисно. І півпіксель ніколи не зустрічає дев'ятищаблеву драбину як півпіксель: 12.5 стає 13 до драбини, за таблицею, яку власник підписав на 5.5, а 13 - це вже нічия, яка йде вгору.

.oc-no з 14.5 у 14 записали як аномалію партії, «єдиний, що вийшов МЕНШИМ». Це шостий рядок таблиці 5.5, і продукт узяв те саме 14.5 → 14 утретє в buy-box.css, у файлі поза цією партією.
Коли вживати

Це реалізація locked-рішення №1: «coach-as-buyer - збережений список клієнтів, тегування замовлень по клієнту, історія по клієнту». Без цих двох екранів тренерського каналу немає взагалі, і саме тому вони мають найбільше екранів у потоці - десять.

Позичати звідси нічого: 38 власних класів - розкладка двох конкретних вузлів. Але одну річ звідси вже позичили: .cl-search стоїть і на coach-session-addclient, тобто пошук списку клієнтів працює і в діалозі вибору. Це той самий пошук, і він правильно один.

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

Правило

Одна людина - одне правило, у двох розмірах. Аватар, ім'я і чип цілі описані так, щоб зміна дійшла до списку й до картки одночасно. Заголовок сторінки взагалі один селектор на два екрани: .cl-h1, .ch-name.

Антиправило

Не віддзеркалюй чужу оболонку перенабором. Екран, який каже «shell mirrors account.html» і потім набирає ті самі 19 блоків, отримує копію, а не дзеркало. Три оголошення з тих 19 уже встигли розійтись до того, як їх видалили.
Обмеження

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

Чотири ряди дій цього файлу беруться патерном .actions. Три власні gap - 9px, 9px, 10px - лишились тут; цей файл сам назвав їх «третім числом на чотирьох рядах дій» ще до того, як патерн з'явився.

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

Нуль :hover, нуль :active, нуль :focus-visible. Кнопки, чипи, поле, статус-пілюля і порожній стан приносять свої стани самі.

Єдиний стан, який малює цей файл, - структурний: .cd-row:last-child знімає нижню лінію останнього рядка даних. Решта «станів» тут - варіанти даних: клієнт із замовленнями і без, список у межах ліміту і на ліміті, і за панель ліміту відповідає upsell.css.

Межі
УмоваЩо змінює
(min-width: 620px).clist у дві колонки. Було 640 - етап 10, раунд 3
(min-width: 860px)відступ 14 вмикається лише тут - нижче 860 він малював і не мав
(min-width: 860px) + @container (min-width: 41rem)спліт-в'ю, етап 10 крок 5, перероблено після критики: .clsplit стає 17.5rem + решта, .clist усередині повертається в одну колонку, .cldetail перестає бути display:none і стає липкою. Двоє воріт, і порядок має значення: спершу оболонка, бо двопанельне робоче місце належить десктопній оболонці, потім місце, бо навіть у ній воно не гарантоване. 41rem = 17.5 + 1.5 + 22 - рейка, зазор і найменша панель, яку варто відкривати. Відкривається на в'юпорті 990 з панеллю 354px; до правки було 860 і 224px
(max-width: 619px)ряд дій картки перестає бути рядом. Було 520 - етап 10, раунд 3
@container (max-width: 22rem)перший контейнерний поріг системи. Рядки .cd-row складаються з 160px 1fr в одну колонку, коли вузька сама КАРТКА, а не екран: та сама картка даних стоїть на всю ширину на coach-client.html і в панелі 224px поруч зі списком, і @media їх не розрізнить, бо в'юпорт в обох випадках той самий

41 позначка [?] - найбільше у всій системі, і всі про геометрію: 9, 11, 14, 15, 21, 56, 160. Відступи мають два правила, що суперечать одне одному на тих самих числах, тож жодне з них не рухається без рішення. Окремо названо 160 - колонка підписів у списку даних клієнта: це єдине 160 у системі, а spec-table.css малює ту саму пару dt/dd зі своєю власною відповіддю.

Розкладка «список і деталь» 10.5

Від широкої ширини список клієнтів перестає бути сіткою і стає лівою колонкою поруч із деталлю: .clsplit кладе їх у дві колонки і повертає .clist в одну, а .cldetail липне до верху й нижче 620 не існує взагалі. Картку клієнта в цій розкладці відкривають кнопкою .ccard-sel - вона успадковує шрифт і колір, бо мусить лишитись НАЗВОЮ, а не виглядати кнопкою.

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

Сторінка звіряє себе з файлом: 44 класи і 0 станів оголошено в coach-clients.css. .coach не рахується - це скоуп, а .btn тут не компонент, а місце в ряду.

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

Від яких порогів: --bp-grid-2col і його дзеркало. Що саме міняється: список клієнтів іде з однієї колонки у дві; нижче точки рядок клієнта складається в стовпчик. Було 640 і 520, обидва поза реєстром. 520 це власне число потоку тренера, яке трапилось тричі - тут, у coach-cabinet і в coach-verify - і не було зареєстроване жодного разу.
Рух

Найчистіший ЗВ'ЯЗОК у продукті, і пак називає його вручну: деталь приходить З БОКУ СПИСКУ, бо саме там щойно були око й палець тренера. --move-md ліворуч, далі нічого; --dur-base, бо це зміна всередині відкритої композиції, а не поверхня, що приходить поверх сторінки. Правило стоїть лише всередині двох воріт спліта: нижче 860 або у вужчому місці другої колонки немає, деталь не поруч зі списком - вона Є сторінка, і зсув убік сказав би протилежне тому, що сталося.

І тут НЕМАЄ проявлення, у чому весь сенс правила. Крок 10.5 переводить фокус на ім'я клієнта тієї ж миті. Якби панель починала з нульової прозорості, скрінрідер читав би ім'я, коли оку ще нічого читати, а клавіатурник дивився б на фокусну рамку поверх невидимої коробки п'яту частини секунди. Панель непрозора кожен кадр руху; змінюється тільки її позиція. Рух не має права приходити пізніше за фокус. Порожня підказка - друга половина того самого обміну - навпаки лише проявляється: за таблицею тону порожній стан приходить спокійно і без зсуву знизу, бо зсув читається як «щось вантажиться», а нічого не вантажиться.

Токени

Прочитані з coach-clients.css, не переписані руками. Жодної помаранчевої ЗАЛИВКИ в усьому файлі - ні --bg-action, ні --text-action: помаранчевий на цих екранах приносять кнопки й панель Pro, а сам список клієнтів увесь у нейтральних ролях. Для екрана, який тренер відкриває щодня, це правильно. Дві помаранчеві ЛІНІЇ файл усе-таки має, і їх додала критика кроку 5: --line-action на наведеній картці й --ring-focus-control на двох нових контролах - імені клієнта в картці та в панелі. Обидва це лінія, а не заливка, і обидва не малюють нічого в спокої: до критики ці контроли падали у власне синє кільце Chrome, яке не знає теми.

Семантичні ролі (12)Примітиви (32)
--bg-page --bg-sunken --elevation-1 --line-action --line-hair --line-inverse --line-strong --ring-focus --ring-focus-control --text-muted --text-primary --text-secondary--container-text --dur-base --dur-fast --ease-enter --ease-standard --font-display --fs-12 --fs-14 --fs-16 --fs-30 --fs-8 --fw-black --fw-bold --fw-semibold --lh-airy --lh-snug --ls-caps --ls-lead --move-md --radius-12 --radius-4 --radius-8 --radius-circle --radius-pill --size-40 --size-44 --space-12 --space-16 --space-2 --space-24 --space-4 --space-8

--fs-8 тут єдине вживання в потоці тренера: це крапка-роздільник .ccard-meta .dot, намальована, а не набрана. --mark-disabled - її колір, і роль обрано за роботою: це мітка, а не текст.

Розмітка
<div class="cl-top"> <div><h1 class="cl-h1">Клієнти</h1><p class="cl-sub">…</p></div> <div class="cl-acts">…</div> </div> <div class="cl-tools"><div class="cl-search"><input></div></div> <div class="clist"> <article class="ccard"> <div class="ccard-hd"><span class="ccard-av">А</span> <div><div class="ccard-nm">Андрій</div> <span class="ccard-goal">Набір маси</span></div></div> <div class="ccard-meta"><b>8 замовлень</b><span class="dot"></span>останнє …</div> <div class="ccard-acts"><a class="btn …">Профіль</a><a class="btn …">Нова сесія</a></div> </article> </div> <main class="wf-page cc-wrap"> <div class="ch"> <div class="ch-id"><span class="ch-av">А</span> <div><h1 class="ch-name">Андрій</h1><span class="ch-goal">Набір маси</span></div></div> <a class="ch-edit">Редагувати клієнта</a> </div> <p class="cc-note">…</p> <section class="cdetails"><h2 class="cd-h">Дані клієнта</h2> <dl class="cd-list"><div class="cd-row"><dt>…</dt><dd>…</dd></div></dl></section> <div class="cc-cta">…</div> <h2 class="oh-h">Історія замовлень</h2> <div class="ohist"><article class="ocard">…</article></div> </main>

.ch-edit без класу btn - це і є той рядок розмітки, який тримає намальовану руками кнопку живою. .dot - порожній <span>, тобто крапка справді намальована.

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

Якорі: .cl-top .cl-h1 .ch-name

10 кольорових екранів - найбільше в потоці: coach-clients · -cap · -empty · -error · -loading і coach-client · -empty · -error · -loading. Плюс .cl-search на coach-session-addclient.

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

Чого бракує

  • .ch - одне ім'я на три компоненти, і .coach не розводить два з них. Сьогодні коштує нуль пікселів, зміряно; завтра - як пощастить
  • .ch-edit - btn--outline руками. Один клас у розмітці видаляє це правило цілком. Крок 6
  • .cl-search - field-grp руками, до якого атом не дотягується, бо розмітка не носить його імен
  • Три мертві оголошення: .cd-list{ margin: 0 } і margin: 0 на dt і dd переказують скидання з base.css:7. Лишені як знайдено - їхня родина це кроки 7.3, 7.51 і 7.69
  • 160px - єдине в системі: колонка підписів списку даних. spec-table.css малює ту саму пару зі своєю відповіддю
  • 41 геометричний літерал під [?] - найбільше у файлі системи

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