Поле
Текстове поле форми. Найбільший атом системи, бо саме тут живуть майже всі стани, які в продукті взагалі є. Нижче - усі шість форм поля, які файл уміє, справжніми класами: сторінка, яка малює поле інлайновими стилями, показує не систему, а свій малюнок.
wireframes/_nav.js, рядки з продукту, жодного інлайнового стилю. Клітинка коду країни - частина поля, а не окремий компонент: вона ділить з ним рамку, тому фокус підсвічує їх разом..cc - незмінна частина значення, на приглушеній підкладці й моношириннимКрок 7. Обхід 39 кольорових екранів знайшов 101 поле, 14 імен, 14 виглядів - і 66 зі 101 набраних Arial. Поле не успадковує font-family, це треба сказати вголос, і сказали це три файли з чотирнадцяти. Пошук у шапці й підписка в підвалі - два найчастіші поля продукту - були не Inter, а їхнє чорнило - чистий #000, якого в палітрі немає. Висот було дев'ять: 37 · 40 · 44 · 45 · 46 · 47 · 60 · 61 · 64.
Драбина 40 / 44 і третього щабля немає, бо в продукті його ніщо не займає. 44 - не нове число: це мінімум пальця й та сама коробка, яку носить іконкова кнопка, тому поле і контрол поруч із ним збігаються. Після кроку 7 усі 101 поле міряють 40 · 44 · 60 (OTP, свій атом) · 80 (textarea), шрифтів два - Inter і моноширинний там, де значення це число, - а чорнило одне.
Матриця осей, а не перелік входжень: кожен рядок це питання, на яке відповідає розмітка, і правило, за яким обирають.
| Вісь | Значення | Правило вибору |
|---|---|---|
| Стан рамки | спокій · ховер · фокус · заповнене · обов'язкове · помилка · вимкнене | Сім станів, кожен зі своєю роллю лінії. Помилка й вимкнене прийшли на кроці 7: до нього перше жило в двох чужих файлах, а другого не було ніде. |
| Тип | один рядок · телефон з кодом · багаторядковий · число · OTP | Тип диктує не вигляд, а клавіатуру й перевірку: телефон отримує inputmode=tel, число - моноширинний і центрування, бо його порівнюють із сусіднім. |
| Що можна ввести | будь-що · тільки цифри | Вирішує значення, а не вигляд: якщо значення поля - це число (код зі SMS, ціна, телефон), поле приймає лише цифри. Поле «Відділення / поштомат - номер або назва» цифру приймає, але його значення числом не є, і обмежувати його не можна. |
| Форма номера | з коміркою +380 · повний номер у полі | Одне правило, дві оправи: якщо код країни стоїть окремою клітинкою, поле тримає дев'ять цифр і показує «67 123 45 67»; якщо поле тримає весь номер, воно саме друкує «+380». Людина може набрати «67…», «067…», «380 67…» або вставити номер із дужками й тире - усі чотири записи означають один номер, і поле зводить їх до одного. |
| Оболонка | .fld у діалозі · .cef у формі клієнта · .frow у фільтрі · .pfield у профілі | Одне поле, чотири оправи. Різниця лише в тому, що поруч: підпис зверху, підпис збоку, два поля в рядок або значення тільки для читання з кнопкою «змінити». |
Рішення живе там, де на нього дивляться. Перепис показав дрейф, крок 5.5 його зняв - і цей блок каже, що саме обрали, що лишили і чому, на сторінці самого компонента, а не тільки в журналі.
| Вісь | Було | Стало | Чому |
|---|---|---|---|
| Радіус | 7 різних | 4 | Ті самі 4/8/12/16: 9, 10 і 11 сіли на 8 і 12. |
| Кегль на мобільному | 136 зі 166 під 16px | 0 з 66 | 16px - нижня межа, під якою iOS зумить сторінку на фокусі. |
| Фокус | три редакції ореолу | | Крок 6.0: один ореол на всі поля, і він не на драбині висот. |
| Кегль числового поля | 13.3px браузерний | | Поле без кегля бере дефолт браузера - значення, якого ніхто не вирішував. |
ПОВЕДІНКА НА ШИРИНІ - етап 10, крок 4
Від якого порогу: жодного. Що саме міняється: поле займає всю ширину свого контейнера і їде разом із ним. Плинне з самого початку, крок 4 нічого тут не змінив.Скрізь, де людина вводить текст: чекаут, профіль, адреси, вхід, фільтр ціни. Рішення 5 - вхід без пароля, тому поля пароля в системі немає і не буде.
Правило
Стан живе на рамці, а обмеження - на значенні. Якщо значення поля це число, поле приймає лише цифри - і не підказкою клавіатури, а насправді:inputmode нічого не забороняє, type=tel взагалі текстовий, а type=number пропускає e, +, - і крапку. Правило виконує design/system/fields.js на двох подіях, якими символ узагалі потрапляє в поле: натиск і вставка.І номер групується сам. Раніше це вміло одне поле з чотирьох, бо код був прив'язаний до
id="wfa-phone" у скрипті екрана. Поведінка була правильна, адреса - ні: правило, прив'язане до одного id, це не правило компонента, а приватна звичка того екрана.Антиправило
Не обмежуй поле за тим, як воно виглядає. «Відділення / поштомат - номер або назва» повне цифр, але його значення не число, і фільтр там відрізав би половину адрес. Обмежує значення, а не сусідство з цифрою.І не показуй помилку самим лише червоним. Червона рамка без тексту не каже, що саме не так, і не існує для читача екрана. Текст помилки стоїть під полем, а не в тості: тост зникає, а виправляти треба тут.
Спокій · ховер (--line-control-hover) · фокус (--line-action плюс --ring-focus, ніколи не браузерний обвід) · заповнене .has (--line-control-filled) · обов'язкове .req (--line-warning) · помилка .err (--line-danger плюс --ring-danger) · вимкнене [disabled]. ::placeholder має власну роль --text-muted.
Крок 7 додав два останні. До нього ховер мали 6 полів зі 101, колір підказки - 9, власний фокус - 72 (решті 29 малював браузер), а вимкненого не було в жодного. Помилка існувала двічі й обидва рази в чужому файлі - .otp .box.err і .pm-b input.err: два компоненти вигадали її окремо, а поле, яким набирають телефон і адресу, показати її не вміло. Тепер це один стан у field.css. Крок 6 забрав друге ім'я: селектор ніс .field--err поряд з .field.err, і замір показав, що охайне ім'я не носить ніхто, а те, що пише рантайм, носять. Стан не змінився ні на оголошення - зникло лише друге ім'я для нього.
Сторінка звіряє себе з файлом: 13 власних класів і 4 станів оголошено в field.css. Нижче - ті, яких на цій сторінці немає ні в демо, ні в розмітці. Чужий контекст (його тут немає) не рахується: у цих селекторах компонент не є підметом, він лише стоїть усередині когось.
Робота: ВІДПОВІДЬ. Рухається: border-color, box-shadow (кільце фокусу). Тривалість --dur-fast (150ms), крива --ease-standard. Значення читаються через var() з tokens.css: підміна токена в браузері веде за собою кожне з них, тобто числа у файлі немає. При prefers-reduced-motion рух зникає, а стан лишається.
Прочитані з field.css, не переписані руками. Колір іде лише через роль, геометрія - напряму з примітива.
| Семантичні ролі (16) | Примітиви (15) |
|---|---|
--bg-page --bg-sunken --bg-surface --field-caret --line-action --line-control-filled --line-control-hover --line-danger --line-hair --line-strong --mark-disabled --ring-danger --ring-focus --text-body --text-muted --text-secondary | --font-mono --fs-12 --fs-14 --fs-16 --fw-bold --fw-semibold --lh-snug --radius-12 --size-20 --size-40 --size-44 --space-12 --space-16 --space-2 --space-8 |
| – | --dur-fast --ease-standard |
Якорі: .fld .cef .txt-field .pfield .ph-field .frow .resend
7 екранів у wireframes/: account-profile-delete.html, account-profile-email.html, account-profile-lang.html, account-profile-phone.html, account-profile-withemail.html, account-profile.html, coach-verify.html
Чого бракує
- Форматування телефону дублюється -
wfAuthDigits()у сірому прототипі досі форматує своє поле поid. Система тепер робить це раніше й для всіх, тому результат однаковий, але два коди на одну роботу лишаються, поки сірий шар заморожений - Вставка коду не розкладається по комірках - вставили «Ваш код 4821» у першу комірку, лишилась одна цифра. Це робота OTP-комірки, а не поля: поле своє вже зробило, відкинувши все, крім цифр
- У поля немає стану помилки -
field.cssне має жодного правила для невалідного значення. Червона рамка в продукті є двічі, і обидва рази її завів собі чужий компонент:otp.cssіreview-modal.css - Жодне поле не позначене -
required0,aria-invalid0,disabled0 на 196 полях. Рамка змінює колір, а читач екрана про це не дізнається - Немає
:disabled- стану, якого немає в продукті, немає і в коді; щойно з'явиться перше вимкнене поле, його треба буде вирішити, а не домалювати - Підпис і поле пов'язані не скрізь - у чотирьох оправах з шести є
for/id, у.frowі.pfieldзв'язок тримається наaria-label - Немає лічильника символів для багаторядкового поля, хоча відгук має ліміт
Не домальовано наперед і не замовчано: етап 09 стартує з цього списку, зведеного в design/kit/docs/architecture.md.