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

Перемикач вигляду

Два вигляди одного списку, і увімкнено рівно один. Сітка або список, тільки на десктопі: на 360 список - єдиний розумний вигляд, тому питання там не виникає.

рівень 1design/system/components/view-toggle.css144 рядкиперебудовано на кроці 7.32
Анатомія

Розмітка взята з listing.html, не намальована для стенда: іконки приходять із набору через icons.js, як на екрані.

наведіть на неактивну половину - і гліф, і край ідуть в акцент; пройдіть Tab - кільце фокуса всередині, бо коробка ріже вміст

На телефоні тут порожньо, і це правда про компонент

Перемикач живе в .ltool, десктопній смузі каталогу, а вона display: none до 860 - разом із усім, що всередині. Тож на вужчому за 860 екрані це демо не малює нічого, і саме так поводиться продукт: подання списком чи сіткою на телефоні не перемикають. Записано, а не замасковано: порожній стенд без пояснення виглядає як зламаний, і на 7.87 власник знайшов рівно такі два - filter-sheet і tabbar, - які насправді були порожні з цієї ж причини.
1Група - обидва варіанти видно завжди. Перемикач, що показує лише поточний стан, читається як кнопка дії
2Обраний - заливка --bg-action-selected, 10% акценту, і гліф --text-action. Заливка, а не тільки колір гліфа
3Волосина між ними - 1px --line-strong, щоб коробка читалась як один контрол, а не два
4Фокус - кільце всередині: коробка має overflow: hidden, і зовнішнє кільце на комірці зрізало б краєм
Перепис: той самий контрол, написаний двічі

Пораховано в браузері на 40 кольорових екранах при 1280 і 390: 7 груп, 14 комірок.

ЕкраниКоміркаhrefІм'яКлавіатура
listing · listing-list · listing-filtered · listing-sheet<a>так, це навігація«Сіткою» / «Списком»нативно
listing-empty · listing-error · listing-loading<span>немаєнемаєнемає

Перше прочитання цього розколу було хибним, і воно виправлене тут. Виглядало, ніби екрани станів зібрані копіюванням, а виправлення - перетворити шість <span> на посилання. Перелік усіх тринадцяти екранів сірого шару з перемикачем, звірений із тим, скільки карток товару кожен тримає, каже інше.

КартокКоміркаЕкрани
> 0<a> живийlisting 10 · listing-list 7 · listing-filtered 6 · listing-sheet 10 · search 9
0<span> мертвийlisting-empty · listing-error · listing-loading · goal-empty · goal-error · goal-loading · search-loading
11<span> мертвийgoal - єдиний виняток

Перемикач живий рівно тоді, коли на екрані є список, який можна перебудувати. На семи порожніх екранах пара інертна, бо перемикати нічого, - і це правильна поведінка, а не недбалість.

Посилання там було б брехнею з href

listing-list.html - єдиний списковий вигляд у всьому продукті. Немає ні goal-list, ні search-list, ні спискового двійника жодного стану порожньо / помилка / завантаження. Тож комірці «Списком» на listing-empty нікуди чесно вести: єдиний доступний пункт призначення тримає сім товарів, а цей екран не знайшов жодного.

Тому <span> лишаються

Погано не те, що це <span>, а те, що вони виглядають натискними: cursor: pointer, повне чорнило, жодного знаку, що ця половина нікуди не веде. Намалювати цей знак означає стан «недоступно», а крок 7.31 відмовився вигадувати його для чипа з тих самих підстав. Записано, а не домальовано.

goal.html - це справжній дефект, і єдиний. 11 товарів, перемикач із готовими aria-label="Сіткою" і aria-label="Списком", і натиснути не можна ні на що, бо goal-list.html не існує. Це відсутній екран, і вирішувати це IA, а не цьому етапу.

Що знайшлось у самому файлі

Селектор писав, а латка стирала

Старий файл казав .vtoggle span - а це кожен span усередині коробки, включно з .uiv-ic, власною обгорткою іконки. Тобто обгортці видавали падінг комірки, фон комірки й приглушене чорнило комірки, а нижче стояли дві правки, які все три знімали назад: .uiv-ic{ background:none; padding:0 } і .on .uiv-ic{ color:--text-action }.

> каже те, що малось на увазі

Комірка - це прямий нащадок коробки. Обидві латки пішли разом із селектором. Знайдено не читанням: я спершу видалив правило іконки, очікуючи спадкування, і в браузері обраний гліф став сірим. Спадкування ніколи його не фарбувало.

Обрана комірка малювала біле чорнило на 10% помаранчевого. --text-oninverse - це білий, а земля обраної комірки - --bg-action-selected, тобто тінт. Сьогодні невидимого немає нічого, бо в комірці іконка й жодного слова (зміряно: нуль текстових вузлів), а іконку рятувала друга правка. Файл казав одне, латка під ним - інше.

А ховер не мав чого фарбувати. .vtoggle a:not(.on):hover вів чорнило комірки в акцент - але в комірці іконка, а іконку фарбував напряму той самий надто широкий селектор. Зміряно на HEAD: при наведенні земля йшла в #FAF9F7, а гліф лишався сірим. Стан наведення на 13 екранах, який не змінював нічого видимого.

Три видимі зміни, перелічені, а не пропхнуті
#ЩоБулоСталоСкільки
1чорнило обраної коміркибілий --text-oninverse--text-action14
2гліф при наведеннісірий - ховер був невидимий--text-action8 досяжних комірок
3кільце фокусасиній контур браузеравнутрішнє кільце --line-action8
Варіанти і розміри

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

ВісьЗначенняПравило вибору
Варіантисітка · списокРівно два. Третій вигляд означає, що каталог не визначився, що показує.
Ширинаприхований до 860На телефоні список - єдиний розумний вигляд, тому вибору там немає.
Комірка44×35, падінг 8/12, гліф 19Одна редакція на обидві половини; різниця в 1px між ними - це волосина-роздільник, а не правило.

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

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

Тільки в Тулбар каталогу і тільки на десктопі. Це не Чип: чип фільтрує що в списку, перемикач вигляду міняє як той самий список показано. І не Перемикач (.sw): той вмикає одну настройку, а тут два рівноправні варіанти, обидва видно завжди.

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

Правило

Обидва варіанти видно завжди. Перемикач, який показує лише поточний стан, читається як кнопка дії.

Антиправило

Не ховай неактивний варіант. Тоді це вже Кнопка з незрозумілим підписом, і людина не знає, що станеться після натискання.
Стани, що є в коді

Три: .on, :hover на неактивній половині і :focus-visible. Останній з'явився на кроці 7.32: прохід по всіх завантажених таблицях стилів у пошуку outline або box-shadow на .vtoggle повертав порожній список, тож вісім досяжних комірок показували типовий синій контур Chrome - те саме, що крок 7.31 знайшов у чипа.

Натиск крок 7.33

Тільки та половина, що не обрана. Натиск на половину, на яку ви вже дивитесь, ні про що не просить, а стану «нічого не змінилось» не буває. --bg-action-soft, а не --bg-surface наведення: натиск усюди в наборі тепліший за наведення, і на десктопі ці два стани мають розрізнятись, коли лягають на одну клітинку в одну секунду.

Шість інертних <span> сюди не входять. Стан натиску на контролі, який нікуди не веде, - це обіцянка, яку цей файл сорока рядками вище пояснив, що не може виконати.

Зміряно дотиком: необрана клітинка #FFFFFF -> #FFF9F5
Холостий контроль

Сторінка звіряє себе з файлом: 1 власний клас і 2 стани оголошено в view-toggle.css. Чужий контекст (.on, .uiv-ic) не рахується: у цих селекторах компонент не є підметом.

Рух

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

Токени

Прочитані з view-toggle.css, не переписані руками. Колір іде лише через роль, геометрія - напряму з примітива.

Семантичні ролі (8)Примітиви (4)
--bg-action-selected --bg-action-soft --bg-page --bg-surface --line-action --line-strong --text-action --text-muted--fs-14 --radius-8 --space-8 --space-12
–--dur-fast --ease-standard

--bg-action-selected має рівно одне вживання на весь продукт - оцю обрану половину. Це навмисно: заливка суцільним акцентом зробила б перемикач гучнішим за головну дію екрана, а принцип 2 каже, що така дія рівно одна.

Розмітка
<span class="vtoggle"> <a href="listing.html" class="on" aria-label="Сіткою"><span class="uiv-ic">…</span></a> <a href="listing-list.html" aria-label="Списком"><span class="uiv-ic">…</span></a> </span>

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

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

Якорі: .vtoggle

13 екранів у wireframes/: goal-empty, goal-error, goal-loading, goal, listing-empty, listing-error, listing-filtered, listing-list, listing-loading, listing-sheet, listing, search-loading, search. У кольорі з них зібрано 7.

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

Чого бракує

  • goal.html: 11 товарів і мертвий перемикач - бо goal-list.html не існує. Відсутній екран, рішення IA
  • Сім інертних перемикачів виглядають натискними - на порожніх екранах вести їх нікуди, але cursor: pointer і повне чорнило цього не кажуть. Потрібен стан «недоступно», якого в продукті немає
  • Немає збереження вибору між екранами - не CSS, але наслідок видно тут
  • Немає :active - момент натискання не показано

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