DarkRiDDeR14 мин

Мобильный сценарий: разбор скрытого действия и безопасный откат

UXFrontend

Фраза «на телефоне нельзя продолжить» уже полезнее, чем «сделайте адаптив». В ней есть симптом, но ещё нет причины. Возможно, кнопка ушла за горизонтальный scroll, details открываются только hover, label стал пустой иконкой или код показывает другой state. Если сразу менять breakpoint, можно временно вернуть кнопку и потерять контекст перед подтверждением. Цена — ошибочное действие, повторная поддержка и release, который невозможно объяснить после жалобы.

Для разбора возьмём один учебный маршрут. Он не опирается на отчёт пользователей, конкретный телефон, heatmap или real browser trace. Мы задаём narrow/coarse/unavailable вручную, планируем summary → details → confirm и смотрим, примет ли модель hover-only. Такой артефакт не отвечает на вопрос, удобно ли людям. Зато он помогает сделать следующий шаг проверяемым: отделить факт скрытого control от предположения о причине.

Соберите наблюдение, которое можно опровергнуть

Карточка разбора
НаблюдениеЧто ещё неизвестноГде искатьБезопасное действие
Нет видимого перехода к подтверждениюскрыт ли он CSS или не построен routeDOM, component state, route contractне выпускать замену до явной альтернативы
Действие доступно только при hoverесть ли keyboard или explicit controlправила visibility и markupдобавить явный control, не удаляя контекст
Итог не читается без широкой таблицыкакие данные обязательны перед confirmsummary model и предметный ownerвыделить краткий summary и details
Новый маршрут вызывает сомнениекакой откат не повторит действиеrelease plan и state ownershipсохранить current path до отдельной проверки

Запись «кнопка пропала» должна содержать условия, иначе следующий инженер не сможет отличить bug от другой конфигурации. В реальном отчёте полезны URL или экран, версия приложения, browser, viewport, zoom, способ ввода, локаль, тестовые данные, начальное состояние и ожидаемый result. В этой статье мы не заполняем эти поля выдуманными значениями. Сам список — не доказательство; он только не даёт принять случайную картинку за воспроизводимый диагноз.

Минимальный разбор одной ветки

Сначала смотрим, является ли «Открыть итог» единственным переходом. Если да, hover-only уже противоречит выбранному учебному контракту. Затем выделяем information before action: заголовок, сумма или иной предметный summary — конкретный набор решает владелец операции. После этого добавляется явный button/link и отдельная ветка details. Только после появления такого маршрута имеет смысл обсуждать spacing, animation и breakpoint. Иначе косметика закрепляет ту же скрытую зависимость.

В fixture отрицательный результат возвращает hover-only-blocked-by-contract и keep-current-path. Последняя строка не означает автоматический rollback приложения. Она лишь запрещает модели объявить новый путь принятым. До выпуска команда всё равно выбирает, как выключать реализацию: флагом, отдельным route, revert commit или ограничением rollout. Этот выбор зависит от репозитория и предметной операции; его нельзя вывести из трёх строк JavaScript.

const profile = {
  viewport: 'narrow',
  primaryPointer: 'coarse',
  hover: 'unavailable',
};

const route = planTeachingMobilePath(profile, {
  id: 'confirm-order',
  label: 'Подтвердить заказ',
  activation: 'explicit-control',
});

console.log(route.accepted); // true
console.log(route.steps.map(({ id }) => id));
// ['summary', 'details', 'confirm']

const rejected = planTeachingMobilePath(profile, {
  id: 'open-summary', label: 'Открыть итог', activation: 'hover-only',
});
console.log(rejected.reason); // hover-only-blocked-by-contract
Диагностический маршрут: наблюдение о скрытом действии ведёт к проверке DOM и contract; hover-only на учебном narrow profile блокируется; явный control ведёт к отдельной browser-проверке; при неопределённости сохраняется current path как rollback boundary.
Схема разделяет доказанный local contract и ещё не выполненные проверки реализации и людей. Она не изображает реальные результаты тестирования.

Как не перепутать диагностику с интерпретацией

Наблюдение: control не отображается в заданном состоянии. Интерпретация: «у всех мобильных пользователей это неудобно». Первое можно проверить DOM и стилями; второе требует метода исследования. Ещё одна опасная интерпретация — «hover: none означает touch-only». Media Queries Level 4 этого не утверждает: primary capability и все доступные input mechanisms различаются. Поэтому код не должен строить бизнес-логику на такой ярлыковой классификации.

Похожая граница есть у pointer events. Наличие pointer event не гарантирует, что action достижим, и отсутствие записи в нашей fixture не означает, что браузер не работает. WCAG 2.1 помогает сформулировать, почему взаимодействие нельзя рассматривать только как mouse path, но не может заменить проверку конкретной разметки. Хороший разбор называет, какой факт подтверждён, а какой ещё является гипотезой.

Порядок исправления

  1. Симптом. Зафиксируйте одно состояние, в котором основной action не виден или требует hover. Сохраните реальные условия только если они действительно известны.
  2. Причина. Проверьте DOM, visibility rules, component state и table/overflow. Не сводите всё к ширине до просмотра владельца route.
  3. Проверка модели. Запустите node web/scripts/upgrade-2022-09.mjs --verify-fixture. Она должна принять explicit route и блокировать hover-only для teaching profile.
  4. Действие. Добавьте видимый labelled control, summary перед ним и доступный путь к details. Не прячьте отмену или ошибку в другом hover menu.
  5. Проверка реализации. Создайте отдельно browser/visual/keyboard сценарий с указанными условиями. Соберите результат, который другой инженер может повторить.
  6. Откат. Если новый путь меняет семантику или скрывает данные, верните current route; не используйте модель как основание для автоматического отката сервера.
  7. Последующая проверка. Если исследование или support signal покажет другой барьер, добавьте его в план работы как новый факт, а не меняйте прошлую диагностику без следа.

Что именно проверять после исправления

В изолированной реализации проверяем, что label совпадает с предметным действием, details доступны до confirm, focus не теряется при раскрытии, error не исчезает из-за нового layout и control не зависит от hover как единственного условия. Потом смотрим узкие и широкие контейнеры с фактическим текстом продукта. Таблица, сложная локаль и длинное имя могут менять layout сильнее, чем условный размер экрана. Эти результаты должны попасть в тест или отчёт, а не в комментарий «на глаз нормально».

Если нужен usability-test, ему потребуются отдельные вопросы, способ набора людей, задача без наводящей подсказки, согласованные заметки и осторожная интерпретация. У этого текста таких данных нет. Нельзя превратить fixture 9/9 в «девять пользователей успешно прошли». Это разные единицы наблюдения: assertion в модели проверяет сравнение строк и порядок массива, а исследование изучает человеческое выполнение задачи.

Граница доказательств
АртефактЧто он подтверждаетЧто он не подтверждает
Учебная fixtureусловный route и ветку rollbackбраузерный рендер или поведение пользователя
Browser testреализацию при зафиксированных условияхпотребности всех аудиторий
Accessibility reviewконкретные критерии и разметку в scopeкоммерческий эффект
Usability studyнаблюдения выбранного метода и выборкивечную истину о каждом устройстве

Граница и следующий шаг

Эта диагностика не даёт готового breakpoint, не задаёт размер target и не выбирает библиотеку компонентов. В ней также нет настоящего rollback, потому что нет production state. Попытка добавить туда реальные browser facts без запуска браузера была бы подменой. Достаточно более узкого, но честного результата: отдельный основной control должен существовать в route, а hover-only на выбранном teaching profile отклоняется.

Следующий шаг — завести короткий issue с наблюдением и неизвестными полями, приложить unit fixture как contract, а затем получить visual evidence в отдельном процессе. Перед rollout запишите владельца, условие остановки и путь отката. После проверки обновите contract только если изменился сам маршрут. Так следующий разбор начнётся не со слов «на мобильном плохо», а с конкретного состояния, границы и действия.

Историческая граница сентября 2022

Фактологическая рамка ограничена тремя исторически доступными документами W3C с immutable URL: Media Queries Level 4 CRD (25.12.2021), Pointer Events Level 2 Recommendation (04.04.2019) и WCAG 2.1 Recommendation (05.06.2018). Будущие версии спецификаций, реальные product signals и device claims в тексте не используются.

Проверяемые источники