Патерн

Ряд дій

Блок закінчився і пропонує вибір: підтвердити або скасувати, зберегти або відмовитись, відкрити клієнта або почати сесію. Дві дії стоять поруч, на один відступ, і залита рівно одна з них.

патернdesign/system/patterns/action-row.css4 правила70 сірих / 15 кольорових екранівзаведено на кроці 9.1
Чому це патерн, а не компонент

Композицію знайшов tools/pattern.mjs по 142 сірих і 88 кольорових екранах. Вона стоїть на 70 сірих екранах - і робить це під 53 різними іменами контейнера.

.eact .act .ceact .addr-acts .ccard-acts .cl-acts .oc-actions .cc-cta .od-acts .ord-acts .ord-acts-c .aord-actions .cv-actions .cv-btnrow .btnrow .cta .me-cta .nl-cta .q-cta .clh-cta .err-btns .co-err-acts .sys-acts .uacts .buyrow .lactions .pstrip .cd-foot .cs-act .ci-links .acts .acact .op-steps .pages ... і ще дев'ятнадцять

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

Компонент цього не вирішує

Кнопка вже є компонентом, і вона правильна. Неправильним було те, як їх ставлять поруч: п'ять різних відступів для однієї роботи, з них два - 9px і 10px - не на щаблі драбини 4 / 8 / 12 / 16. coach-clients.css помітив це сам і записав у власному коментарі: «третє число на чотирьох рядах дій».
Анатомія

Живий патерн, з реальними рядками з продукту. Розмітка взята з account-addresses.html, не намальована для стенда.

картка адреси: обидві дії контурні, бо жодна з них не є головним кроком екрана
1Контейнер - .actions, і це ВСЕ, що патерн оголошує: display: flex, gap і перенос. Ні кольору, ні рамки, ні розміру
2Дії - кнопка своїм фінішем: btn--accent на головній, btn--outline на сусідній. Патерн не знає, який фініш обрано, і не має знати: ранг - робота кнопки
3Відступ - --space-12, найчастіше вживаний з п'яти, які продукт носив до переїзду
4Перенос - flex-wrap: wrap у .actions, і це твердження, а не підрахунок голосів: дві дії, що не влазять у 360px, мають упасти на другий рядок, а не виїхати за екран. Ряд, що ділить ширину замість переносу, каже .actions--even
Варіанти

Три, і кожен вичитаний з екранів, а не придуманий тут.

.actions - основа. Панель Pro на coach-clients-cap: залита рівно одна дія
.actions--center - під блоком, який сам відцентрований: картка верифікації, порожній стан
.actions--even - дві дії ділять ширину порівну і не переносяться: підвал картки, де жоден підпис не можна обрізати

Четвертого варіанта немає, і це перевірено приладом

.actions--even вийшов у світ без жодного носія, і tools/dead-sel.mjs сказав це двома рядками «МЕРТВИЙ» у ту саму мить, коли теку патернів додали в його предмет. Вибір «вжити або видалити» став заміром, а не вподобанням: .ccard-acts тримав flex-wrap: nowrap і .ccard-acts .btn{ flex: 1 } руками, а це і є цей модифікатор. Обидва оголошення видалено, розмітка каже actions--even.
Коли вживати

У трьох місцях шляху, і всі три - момент рішення, а не момент перегляду.

Місце шляхуЩо там за вибірЕкран
Підвал карткиоб'єкт у списку пропонує дві дії над собою: подивитись або продовжитиcoach-clients · account-addresses · account
Кінець блокаблок дочитано, і він пропонує наступний крок плюс відмовуcoach-clients-cap · coach-landing · home-cart
Підвал діалогупідтвердити або скасувати, і скасування завжди першеще не переведено, див. «Обмеження»

Головний тест - «One orange per view» з DESIGN.md: акцент означає рівно одне, «тут натиснути». Ряд дій - це місце, де правило перевіряється найчастіше, бо в ньому дві кнопки поруч. Залита - одна.

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

Правило

Беріть патерн, коли поруч стоять дві дії одного блока. Ім'я контейнера при цьому лишається своє - class="ccard-acts actions": воно каже, ЧИЙ це ряд, а патерн каже, ЩО це ряд.

Антиправило

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

Коли патерн НЕ береться: коли композиція одноразова або відрізняється порядком. Підвал шухляди кошика (.cd-foot) - це grid з підказкою під кнопками, а не ряд; смуга покупки (.buyrow) вирівнює вміст по центру і тримає лічильник між кнопками. Обидві лишились собою і це правильно: патерн - стала композиція, а не будь-які дві кнопки в одному батькові.

Обмеження

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

Новий ряд дій пише class="actions". Відхилення пишеться .x.actions{ } у власному файлі компонента, ніколи на екрані - і саме тут крок 9.1 помилився вперше: .actions і голий клас контейнера важать однаково (0,1,0), а патерни імпортуються останніми, тож відступ патерна тихо перебивав власний відступ контейнера і зсував розкладку на 4px. Скоупнуті .coach .x вижили при (0,2,0), і дефект вилетів рівно на чотирьох нескоупнутих.

Два ряди дій ще не переведені, і це сказано вголос. .ceact і .cedlg .act - власний ряд діалогу клієнта, вісім сірих екранів і два кольорові: його розмітку будує wireframes/_nav.js, спільний скрипт ОБОХ корпусів, а сірий корпус цей етап не редагує. .sys-acts - ряд службової сторінки, нуль кольорових входжень, тож доводити пікселями нема чого. Обидва в беклозі для етапу 12.

Де стоїть

Доказ існування патерна, а не ілюстрація: 15 кольорових екранів поіменно, і кожен відкривається.

КонтейнерЩо це за рядЕкрани
.ccard-actsпідвал картки клієнта, дві дії ділять ширинуcoach-clients · coach-clients-cap · coach-clients-loading
.ci-linksдва посилання рядка кошикаcart · cart-coach · cart-oos
.cc-cta · .oc-actionsзаклик картки клієнта і дії картки замовленняcoach-client · coach-client-loading
.addr-acts«Редагувати / Видалити» на картці адресиaccount-addresses
.aord-actionsдії рядка замовлення в кабінетіaccount
.cl-actsінструменти списку клієнтівcoach-clients
.uactsдії панелі Procoach-clients-cap
.clh-ctaзаклик шапки лендінгу тренераcoach-landing
.od-acts · .ord-actsдії замовлення тренера і його спискуcoach-order · coach-orders
.cv-btnrowдії картки верифікації, відцентрованіcoach-verify-loading
.cs-actдії полиці кошика на головнійhome-cart

Переведення доведено пікселями: tools/tree-diff.mjs проти дерева до правки, 30 порівнянь на 360 і 1280, зрушило 0, перейменовано 240 рядків. Позитивний контроль у приладу є: перший прогін цього ж набору казав «зрушило 10» і назвав рід кожного зсуву.

Що переїхало, файл за файлом

Вирізано звідти, вставлено сюди - не скопійовано. Правило, що лишилось одночасно у двох місцях, це дефект, а не підстраховка.

Файл компонентаКонтейнерЩо переїхалоЩо лишилось на місці
upsell.css.uactsdisplay, gap, flex-wrapmargin-top: 6px
coach-verify.css.cv-btnrowусе правило цілком–
coach-landing.css.clh-ctadisplay, gap, flex-wrapmargin-top: 20px
address-card.css.addr-actsdisplay, flex-wrapgap: --space-8
order-row.css.aord-actionsdisplay, flex-wrapgap: --space-8
coach-order.css.od-actsdisplay, flex-wrapgap: 10px
coach-cabinet.css.ord-actsdisplay, flex-wrapgap: 10px
coach-clients.css.cl-actsdisplay, flex-wrapgap: 9px
.ccard-actsdisplay, nowrap і .btn{flex:1}gap: 9px, margin-top: auto
.cc-ctadisplay, flex-wrapgap: 10px
.oc-actionsdisplay, flex-wrapgap: 9px
trust-strip.css.cs-actdisplay, flex-wrapgap: --space-8
cart-row.css.ci-linksdisplaygap: --space-16, nowrap

П'ять відступів на одну роботу - це не полагоджено тут навмисно. Крок з патерном це рефакторинг, і його приймання - нуль зрушених пікселів. Кожне відхилення лежить одним оголошенням в одному файлі й записане в беклог списком 4 у формі «змінна -> значення -> чому». Вкласти зміну значення в переїзд - це рівно те, як рефакторинг перестає бути доказовим.

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

Сторінка звіряє себе з файлом: 3 власні класи. Станів патерн не має і не може мати - він не інтерактивний: інтерактивні тут кнопки всередині, і їхні чотири стани показує їхня сторінка.

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

Від якого порогу: жодного, і це відповідь раунду 4 цілком. Патерн у цій системі один, і в ньому нуль медіазапитів: flex-wrap: wrap стоїть у базовому правилі з кроку 9.1, а .actions--even каже «поділіть ширину» модифікатором розмітки, а не числом. N = 1, M = 1, K = 0. Композиція, зібрана з компонентів, які вже вміють ширину, не має власної відповіді на неї - і саме тому раунд патернів найкоротший із чотирьох, а не тому, що його зробили формально. Одне правило перевірено і лишилось не тут: .cs-act у trust-strip.css нижче точки бере всю лінію і ділить її порівну - друга половина цього і є .actions--even. Модифікатор не вмикається за шириною без запиту, тож правило лишається у свого контейнера, складене на 619.
Рух

Патернів у системі один, і власного переходу композиції він не отримує. Це відповідь, а не пропуск, і вона називається числом: action-row.css не оголошує жодного transition, а рух, який на ньому видно, приходить з button.css - двох контролів, з яких ряд складено. Той самий клас, що icon.css на кроці 3: стан в одному файлі, рух в іншому.

Чому композиції тут нема що дати. Перехід патерна відповідає на питання «що з'являється, звідки і в якому порядку». Ряд дій ніколи не з'являється сам: він приходить разом із блоком, який його тримає - підвалом діалогу, ногою картки, порожнім станом, - і цей блок уже має свою роботу ЗВ'ЯЗОК. Дати ряду власний вихід означало б анімувати момент, для якого не називається жодна з трьох робіт, тобто рівно те, що пак називає сиротою на виліт. Черговість появи двох кнопок - найдешевший спосіб завести конфеті поруч із джерелом, яке його виправдовує.

Токени

Прочитані з action-row.css, не переписані руками. Кольору тут немає жодного, і це не випадковість: патерн збирається з компонентів і токенів, а колір несе роль, яку оголошує компонент.

Семантичні ролі (0)Примітиви (1)
–--space-12
Розмітка
<!-- ряд дій блока: власне ім'я плюс патерн --> <div class="ccard-acts actions"> <a class="btn--outline btn--s" href="#">Профіль</a> <a class="btn--accent btn--s" href="#">Нова сесія</a> </div> <!-- дві дії ділять ширину і не переносяться --> <div class="actions actions--even"> ... </div> <!-- під відцентрованим блоком --> <div class="actions actions--center"> ... </div>

Файл: design/system/patterns/action-row.css, підключений у design/system/index.css після компонентів - патерн збирається з них, тож у каскаді стоїть нижче.