К содержанию

Навигация

Фоновые эффекты

Фоновый эффект — анимированный фон, который рисуется в одной области страницы: художественная половина страницы входа, фон крупного блока, группа карточек, сквозь которые видна одна сцена. Эффект состоит из манифеста effect.json и одного модуля JavaScript. По манифесту продукт показывает эффект в списке, описывает его и строит форму настроек, не запуская его код. Правила эффекта задаёт стандарт simai.effect 1.1.0; Framework даёт схему манифеста, SF.Effects в ядре и набор проверок, готовые эффекты лежат в каталоге эффектов, а установка, включение и хранение настроек остаются за продуктом.

Манифест

JSON
{
  "schema": "simai.effect",
  "schema_version": 1,
  "id": "sample-dots",
  "version": "1.0.0",
  "label": {"ru": "Точки", "en": "Dots"},
  "entry": "sample-dots.js",
  "surfaces": ["sign-in", "hero"],
  "schemes": ["dark", "light"],
  "capabilities": ["windows"],
  "settings": [
    {"key": "count", "type": "integer", "label": {"ru": "Сколько точек"}, "default": 24, "min": 4, "max": 200},
    {"key": "speed", "type": "number", "label": {"ru": "Скорость"}, "default": 1, "min": 0.25, "max": 4, "step": 0.25},
    {"key": "shape", "type": "choice", "label": {"ru": "Форма"}, "default": "round",
      "options": [{"value": "round", "label": {"ru": "Круг"}}, {"value": "square", "label": {"ru": "Квадрат"}}]}
  ],
  "needs": {"network": false}
}
Поле Обязательно Что задаёт
schema да имя формата simai.effect вместе с "schema_version": 1; схема принимает и метку simai.effect.v1, при ней schema_version не нужен
schema_version с simai.effect 1
id да имя эффекта: строчная латинская буква, затем от 1 до 40 строчных букв, цифр или дефисов
version да версия эффекта <старшая>.<младшая>.<исправление>
label да подпись по языкам: {"ru": "…", "en": "…"}, до 200 символов
author нет автор, до 200 символов
entry да файл модуля рядом с манифестом, .js или .mjs
styles нет до восьми файлов .css рядом с манифестом
preview нет картинка для списка: .png, .jpg, .jpeg или .webp; показывает домашнюю схему
surfaces да области страниц, для которых эффект можно выбрать, например sign-in
schemes нет темы, для которых эффект нарисован: dark, light или обе; первая — домашняя схема. Без поля эффект рисует обе
pair нет эффект другой схемы в той же роли — см. Пара
capabilities нет ["windows"]: эффект можно рисовать в режиме окон
settings да до 40 настроек; может быть пустым списком
needs да ровно {"network": false}: эффект не ходит в сеть

Других полей нет. Схема манифеста — версия 1.2.0, она лежит в поставке ui (distr/core/contracts/effect.v1.schema.json); манифест без schemes, pair и capabilities проходит её так же.

Пара

pair называет эффект другой схемы, который играет ту же роль. Его называет только эффект с одной схемой. Пара проверяется так же строго, как сам эффект:

  • идентификатор ищется в том же каталоге и сверяется с отпечатком SHA-256 из его индекса до запуска;
  • адрес https://…/effect.json вне закреплённого каталога — чужой эффект: он работает только в изолированном фрейме. Такого исполнителя Framework не поставляет, поэтому чужую пару SF.Effects не запускает: размещение скрывается с причиной foreign-pair-needs-sandbox и отправляет sf-effect-refused.

Доверенный эффект никогда не подтягивает недоверенную пару на страницу.

Настройки

У каждой настройки есть key (латинская буква, затем до 40 букв и цифр), type, label и default, который сам проходит проверку настройки. Необязательные поля — hint, unit и step.

type Что хранит Что обязательно
choice одно значение из options options — список {value, label}
integer целое число в границах min и max
number число в границах min и max
boolean да или нет —
string строка без переноса строки max — наибольшая длина
text многострочный текст max — наибольшая длина
color цвет #rgb, #rrggbb или #rrggbbaa —
file файл сайта: адрес или идентификатор, который продукт уже проверил, или пусто ничего; необязательный accept называет виды файлов, например image/webp

Значение вне границ не подрезается, а считается неверным. Хранимые значения приводятся только там, где смысл очевиден: числовая строка для числа, "1", "0", "true", "false" для логического значения. Форму настроек продукт строит из settings своим представлением записи, а не пишет руками для каждого эффекта.

Схемы, цвет и контраст

Каждая схема эффекта нарисована для своего фона: тёмная — для тёмного, светлая — для светлого, а не перевёрнутая картинка другой схемы. Область, в которой эффект нарисован, получает класс этой схемы (theme-dark или theme-light), какой бы ни была тема страницы, поэтому текст и элементы управления над эффектом берут роли его темы. Класс темы область не красит: своей области задайте фон и цвет текста, например bg-surface color-on-surface (Участок другой темы).

Эффект рисует тонами палитр — --sf-<палитра>-<тон>, например --sf-primary-40 или --sf-neutral-98. Тоны одинаковы во всех темах и несут цвета проекта; тон для каждой схемы эффект выбирает сам. Ролями темы (--sf-surface, --sf-on-surface и другими) эффект не рисует: они меняются под ним вместе с темой области и на странице без таблиц Framework их нет. Тон читают через короткоживущий пробный элемент, чтобы цепочки var() и light-dark() разрешились, держат запасной цвет для страницы без таблиц Framework и читают тоны заново, когда меняется тема или цвета проекта (Цветовые примитивы и палитры).

Контраст текста над эффектом при настройках по умолчанию, на самом ярком кадре:

Текст Роль Контраст не ниже
основной --sf-on-surface 4.5:1
приглушённый --sf-on-surface-variant 3:1

Приглушённый текст над эффектом поэтому только крупный — 24px, или 18.66px жирным, как WCAG допускает при 3:1. Мелкий текст над эффектом берёт основную роль. Кто поднял настройку выше значения по умолчанию, отвечает за получившийся контраст: обещание эффекта — его значения по умолчанию.

При настройках по умолчанию эффект рисует одно и то же: без Math.random без затравки. Случайность берут с постоянной затравкой или с затравкой из настроек, иначе проверки контраста и схемы набора дают разный результат от запуска к запуску.

Модуль эффекта

Модуль экспортирует одну функцию mount(host, settings, context) и возвращает объект с методами update(settings, context), pause(), resume() и destroy(). context содержит:

Поле Что значит
reducedMotion человек просил меньше движения
locale язык страницы
scheme схема, в которой эффект рисует сейчас: dark или light
JavaScript
export function mount(host, settings, context) {
  const canvas = document.createElement('canvas');
  canvas.style.cssText = 'position:absolute;inset:0;inline-size:100%;block-size:100%';
  host.append(canvas);
  const ratio = Math.min(globalThis.devicePixelRatio || 1, 2);
  let values = settings;
  let scheme = context.scheme;
  let frame = 0;
  let running = false;
  const paint = () => { /* рисует кадр по values тонами схемы scheme с плотностью ratio */ };
  const tick = () => { paint(); frame = requestAnimationFrame(tick); };
  const start = () => { if (running || context.reducedMotion) return; running = true; frame = requestAnimationFrame(tick); };
  const stop = () => { running = false; cancelAnimationFrame(frame); };
  paint();
  start();
  return {
    update(next, nextContext) { values = next; scheme = nextContext.scheme; paint(); },
    pause: stop,
    resume: start,
    destroy() { stop(); canvas.remove(); }
  };
}

Эффект рисует только внутри host — добавляет туда свой canvas или video — и не трогает остальную страницу. Плотность пикселей он ограничивает двумя. При reducedMotion он рисует один неподвижный кадр и больше кадров не просит. Новые настройки и смена схемы приходят в update(settings, context) без повторного монтирования, а после destroy не остаётся ни узлов, ни кадров, ни наблюдателей, ни слушателей.

Каталог эффектов

Официальный каталог — effects.simai.io: галерея эффектов, их схем и настроек. Исходники и файлы каталога лежат в репозитории simai/ui-effects; страница подключает каталог по адресу с коммитом, а не с веткой. Выпуск каталога v2.0.0 — коммит d955c66ae024552f5e2f98c418e2923959484877, 17 эффектов без пар:

Code
https://cdn.jsdelivr.net/gh/simai/ui-effects@d955c66ae024552f5e2f98c418e2923959484877/
Схемы Эффекты
обе constellation-net, hex-conduits, glyph-tide (домашняя — тёмная); contour-map, halftone-tide (домашняя — светлая)
только тёмная aurora-curtain, comet-flow, nebula-mesh, neon-horizon, abyss-caustics, rain-glass, liquid-chrome
только светлая mist-gradient, daylight-caustics, leaf-shadows, paper-facets, paper-hills

Все 17 объявляют capabilities: ["windows"]. Каталог подключают до core.js:

HTML
<script>
  window.SF_BOOT_CONFIG = {
    effects: {
      catalogue: 'https://cdn.jsdelivr.net/gh/simai/ui-effects@d955c66ae024552f5e2f98c418e2923959484877/',
      indexSha256: '9a594fa4d9bb452419aaafbbd4af72443034ce5b1c71d6805be95b1fb868e01e',
    },
  };
</script>
<script src="…/core/js/core.js"></script>
Ключ SF_BOOT_CONFIG.effects Обязательно Что задаёт
catalogue да адрес каталога; закрепляет его коммит в адресе
index нет путь индекса от адреса каталога, по умолчанию catalogue/index.json
indexSha256 нет отпечаток SHA-256 файла индекса: индекс тоже сверяется

Каждый файл эффекта — effect.json, модуль и стили из styles — загружается один раз, и его SHA-256 сверяется с индексом каталога (effects[].files[].sha256) до того, как что-то запустится. Модуль выполняется из проверенных байтов, повторно он не загружается. Проверке нужен crypto.subtle, то есть защищённый контекст: страница по https или localhost. Эффект по адресу вне закреплённого каталога — чужой: он работает только в изолированном фрейме, и SF.Effects его не запускает, а отклоняет с причиной foreign-effect-needs-sandbox.

Подключение разметкой

Область с атрибутом data-sf-effect получает эффект из каталога после загрузки страницы. Когда каталог задан, ядро так же находит области, добавленные позже, и убирает размещение, когда область уходит со страницы.

Атрибут Где Что задаёт
data-sf-effect область идентификатор эффекта в каталоге или адрес его effect.json под адресом каталога
data-sf-effect-settings область настройки — объект JSON; неверный JSON заменяется значениями по умолчанию с предупреждением в консоли
data-sf-effect-theme область режим темы: auto (по умолчанию), dark или light
data-sf-effect-windows группа эффект для режима окон, вместо data-sf-effect
data-sf-effect-window карточка группы карточка — окно, сквозь которое видна сцена

Эффект рисует в слое [data-sf-effect-layer], который ядро ставит первым потомком области. Статичная область получает position: relative, и каждая — isolation: isolate, поэтому слой остаётся под содержимым. Состояние размещения область показывает атрибутами:

Атрибут Значения
data-sf-effect-state loading, running, hidden, refused, failed
data-sf-effect-reason почему эффект скрыт или отклонён; есть только при hidden и refused

Режим темы

У размещения есть режим темы: auto — как у страницы, dark — всегда тёмная, light — всегда светлая. Что рисовать, решается по порядку:

  1. сам эффект, если он рисует нужную схему;
  2. его пара, если она рисует нужную схему;
  3. в auto эффект только с тёмной схемой остаётся тёмным и на светлой странице;
  4. иначе эффект скрыт: область получает класс нужной темы и показывает обычную поверхность. Эффект только со светлой схемой на тёмной цели не показывается — читатель выбрал тёмную тему, чтобы не слепило.

В auto размещение следует за страницей: за классом темы на <html>, за событием sf-theme-change и за prefers-color-scheme. Тот же эффект переключает схему через update без повторного монтирования. Редактор предлагает только те постоянные режимы, которые эффект или его пара умеют рисовать (allowedModes).

Причина скрытия Когда
light-only-on-dark auto, тёмная страница, эффект только светлый и без пары
mode-not-drawable постоянный режим, который ни эффект, ни пара не рисуют
foreign-pair-needs-sandbox нужна пара, а она задана чужим адресом
pair-refused пару каталог не выдал: её загрузка отклонена
pair-not-loaded нужна пара из каталога, а размещению её не передали
pair-without-windows в режиме окон нужна пара, а она не объявляет windows
unknown-theme-mode режим не auto, dark или light

Режим окон

В режиме окон один эффект рисуется один раз — в слое размером с группу — и виден только сквозь карточки-окна, поэтому сцена непрерывна от окна к окну. Маску окон ядро перестраивает при изменении размеров, прокрутке и при добавлении, удалении или пометке карточек. Только окна получают тему эффекта; остальные карточки сохраняют тему страницы. Свой фон окна не рисуют. Режим доступен только эффекту с capabilities: ["windows"]: разметка с другим эффектом получает refused и причину windows-not-declared.

Подключение из скрипта

SF.Effects доступен сразу после выполнения core.js:

Член Что делает
checkEffectManifest(manifest) проверяет манифест; возвращает список проблем, пустой — манифест верен
checkSetting(setting, value) проверяет одно значение; возвращает {ok, value}
effectSettings(manifest, stored) превращает хранимые значения в настройки эффекта: каждый ключ манифеста, верное хранимое значение или значение по умолчанию; возвращает {settings, invalid}, где invalid — ключи, чьи значения отброшены
effectSchemes(manifest) схемы эффекта; без schemes — ['dark', 'light']
pairIsForeign(manifest) true, если пара задана адресом, а не идентификатором каталога
pageScheme(document?) 'dark' или 'light': класс темы на <html>, без него — системная настройка
allowedModes(manifest, {pair?}) режимы, которые может предложить редактор: всегда 'auto', постоянный — только если его рисует эффект или пара из каталога. pair — манифест пары, если он известен
resolveTheme(manifest, {pageScheme?, themeMode?, pair?}) что рисовать: {effect: 'self' | 'pair', scheme} (с pair для пары) или {hidden: true, reason}
mountEffect(host, options) монтирует загруженный модуль по правилам; с themeMode — размещение с режимом темы
mountWindows(group, options) монтирует загруженный модуль в режиме окон
loadEffect(reference, {catalogue?}) загружает эффект из каталога с проверкой целостности
placeEffect(element, options) загружает эффект из каталога и размещает его в области или за окнами группы
EFFECT_SCHEMA метка формата simai.effect.v1

loadEffect и placeEffect

loadEffect(reference, {catalogue}) принимает идентификатор эффекта или адрес его effect.json под адресом каталога; catalogue по умолчанию берётся из SF_BOOT_CONFIG.effects.catalogue. Он возвращает обещание {id, url, manifest, module, styles}, а отказ — ошибку с полем reason:

reason Почему
integrity отпечаток файла не совпал с индексом; файл назван в detail.file
foreign-effect-needs-sandbox адрес вне закреплённого каталога
no-catalogue каталог не задан
not-in-catalogue эффекта нет в индексе
file-not-in-index файла нет в записи эффекта в индексе
invalid-index индекс не читается или не того формата
invalid-manifest манифест не проходит проверку
manifest-mismatch id манифеста не совпадает с записью индекса
fetch-failed файл не загрузился
module-failed модуль не выполнился или не экспортирует mount
no-integrity-check нет crypto.subtle: страница не в защищённом контексте
no-effect ссылка на эффект пустая

placeEffect(element, {effect, settings, themeMode, windows, catalogue, locale}) загружает эффект, а если его пара — идентификатор каталога, то и пару, и рисует его в слое под содержимым области. С windows (true или селектор окон) он рисует эффект за окнами группы. Возвращает объект размещения или null, если эффект отклонён: тогда у области data-sf-effect-state="refused" и data-sf-effect-reason. Эффект без capabilities: ["windows"] в режиме окон отклоняется с причиной windows-not-declared.

mountEffect и mountWindows

mountEffect и mountWindows монтируют модуль, который продукт уже загрузил и проверил сам: встроенный эффект продукта.

JavaScript
const manifest = await fetch('/effects/sample-dots/effect.json').then((response) => response.json());
const module = await import('/effects/sample-dots/sample-dots.js');
const host = document.querySelector('.sign-in-art');

const effect = SF.Effects.mountEffect(host, {manifest, module, stored: savedValues, scheme: 'dark'});
effect.update(newValues, {scheme: 'light'});

const placement = SF.Effects.mountEffect(host, {manifest, module, stored: savedValues, themeMode: 'auto', area: section});
placement.update(savedValues, {themeMode: 'dark'});
placement.destroy();
Вариант mountEffect Что делает
без themeMode эффект рисует в схеме scheme, а если не умеет — в домашней; update(settings, {scheme}) меняет настройки и схему
с themeMode размещение: схему и эффект выбирает режим темы; pair — пара из каталога, уже загруженная, как {manifest, module}; area — элемент, который получает класс темы, по умолчанию host; update(settings, {themeMode}) меняет настройки и режим

Объект размещения, кроме update, pause, resume и destroy, отвечает полями effect ('self', 'pair' или null, если эффект скрыт), resolution (ответ resolveTheme), scheme (нарисованная схема или null) и themeMode. После destroy область возвращает свои классы темы. Пара, заданная адресом, не запускается, даже если её модуль передан: размещение скрывается с причиной foreign-pair-needs-sandbox.

mountWindows(group, {manifest, module, stored, pair, locale, themeMode, windows}) рисует эффект за окнами группы; windows — селектор окон, по умолчанию [data-sf-effect-window], themeMode по умолчанию auto. Метод refresh() перестраивает маску, если окна изменились не через разметку, например классом по своему селектору. Эффект без capabilities: ["windows"] mountWindows не принимает и выбрасывает TypeError.

mountEffect выбрасывает TypeError, если манифест неверен или модуль не экспортирует mount. Каждое монтирование:

  • ставит элементу, в котором рисует эффект (host; у placeEffect и разметки — слою), aria-hidden="true", pointer-events: none и data-sf-effect с именем эффекта — фон не читается экранным диктором и не мешает указателю;
  • передаёт эффекту настройки через effectSettings, поэтому неверное или отсутствующее значение заменяется значением по умолчанию;
  • вызывает pause(), пока вкладка скрыта или область вне экрана, и resume(), когда она снова видна;
  • монтирует эффект заново, когда человек включает или выключает уменьшение движения, — неподвижный кадр появляется сразу;
  • после destroy() очищает этот элемент и снимает свои слушатели. Методы можно вызывать в любом порядке и повторно.

События

Событие Когда detail
sf-effect-refused загрузка эффекта отклонена, или размещение скрыто из-за чужой или отклонённой пары; всплывает от области, в консоли — предупреждение {effect, reason, …}
sf-effect-error эффект выбросил ошибку в update, pause, resume или destroy, или размещение из разметки не смонтировалось (phase: 'mount'); всплывает {effect, phase, message}

Ошибку монтирования ловит продукт: он показывает вместо эффекта свой эффект по умолчанию. Эффект, который продукт не поставляет и не проверял сам, запускается только во фрейме с sandbox без allow-same-origin, со строгой политикой безопасности содержимого и получает проверенные настройки сообщением.

Набор проверок

Перед тем как показать эффект в списке, продукт прогоняет на нём набор проверок — скрипт scripts/effect-kit.mjs из исходников Framework (simai/ui-source, ревизия выпуска). Скрипту нужны Node.js и Playwright с установленным Chromium. Он принимает папку эффекта (effect.json и файлы, которые тот называет) и корень собранного Framework — выход sf-build framework --out (Сборка пакета: sf-build): скрипт берёт из него core/core/js/core.js. Подойдёт и папка, в которой core/core — это distr/core поставки ui того же выпуска.

Bash
node scripts/effect-kit.mjs ./effects/sample-dots ./framework-build

Скрипт печатает каждую проверку с результатом (ok или FAIL и подробности) и завершается с кодом 1, если хотя бы одна не прошла. Одиннадцать проверок проходит каждый эффект:

Проверка Что проверяет
manifest манифест проходит checkEffectManifest; если нет, остальные проверки не запускаются
defaults значение по умолчанию каждой настройки верно
mounts mount() возвращает update, pause, resume, destroy и рисует в области
no-network эффект не запрашивает ничего, кроме своих файлов
still-motion при уменьшении движения эффект рисует и перестаёт просить кадры
hidden-tab пока вкладка скрыта, кадры не запрашиваются
pixel-ratio canvas не больше двойного размера области
update update() с новыми настройками не монтирует эффект заново: узлы области остаются
cleanup после destroy() область пуста и кадры не запрашиваются
remount после destroy() эффект монтируется снова
accessibility область вне дерева доступности и не принимает указатель

Остальные проверки идут по тому, что объявляет манифест:

Проверка Что проверяет
scheme-<схема> для каждой объявленной схемы: в области .theme-<схема> каждый снятый кадр нужной полярности — средняя относительная яркость ниже 0.18 для тёмной, не ниже 0.18 для светлой
contrast-<схема> на худшем из пяти кадров при настройках по умолчанию --sf-on-surface даёт не меньше 4.5:1, а --sf-on-surface-variant — не меньше 3:1 против 95 % пикселей
scheme-switch эффект с двумя схемами переключается через update(settings, {scheme}) без повторного монтирования, и кадр меняет полярность
windows эффект с windows нарисован один раз за тремя окнами под маской: вне окон ничего не видно, сцена охватывает всю группу, и это держится после сужения группы
pair пара-адрес отмечена как требующая изолированного фрейма и не запускается на странице; пара-идентификатор — как найденная в каталоге и сверенная с его индексом

В исходниках лежат образцы: tests/fixtures/effect-sample проходит все проверки, tests/fixtures/effect-schemes — эффект с двумя схемами и режимом окон, а tests/fixtures/effect-bad нарушает четыре правила — ходит в сеть, рисует при уменьшении движения и в скрытой вкладке, продолжает просить кадры после destroy — и не проходит no-network, still-motion, hidden-tab и cleanup.

Требования стандарта

Стандарт simai.effect 1.1.0 — двадцать требований, все обязательные.

Требование Суть
manifest-describes-everything Эффект описан только манифестом: имя, версия, подпись, модуль, стили, превью, области, схемы, пара, возможности, настройки и потребности; продукт показывает и настраивает его, не запуская код, а форму настроек строит из манифеста своим представлением записи
settings-are-typed-and-bounded У каждой настройки ключ, тип, подпись и верное значение по умолчанию; числа называют границы, строки — длину, выбор — варианты, файлы — виды файлов сайта
values-checked-before-use Каждое хранимое значение проверяется перед сохранением и перед передачей эффекту; неверное или отсутствующее заменяется значением по умолчанию
one-module-one-mount Модуль экспортирует mount(host, settings, context) и отвечает методами update, pause, resume, destroy; новые настройки и смена схемы приходят через update(settings, context) без повторного монтирования
draws-in-its-host-only Эффект рисует только в своей области, с плотностью пикселей не больше двух, и не трогает остальную страницу
no-network Эффект не делает запросов: только свои файлы и файлы сайта, которые называют его настройки
reduced-motion-still При уменьшении движения — один неподвижный кадр; включивший настройку человек получает его сразу
hidden-tab-idle В скрытой вкладке эффект ничего не рисует и не просит кадры
not-in-the-way Область вне дерева доступности и не принимает указатель: эффект стоит под элементами управления страницы
clean-destroy После destroy не остаётся узлов, кадров, наблюдателей и слушателей, и эффект можно смонтировать снова
schemes-and-pair-declared Эффект объявляет свои схемы, домашнюю первой; каждая нарисована для своего фона; без схем — обе. Эффект с одной схемой может назвать пару другой схемы
theme-follows-the-placement У размещения режим темы auto, dark или light; порядок выбора — эффект, пара, тёмный эффект на светлой странице, иначе обычная поверхность; редактор предлагает только рисуемые режимы
area-takes-the-drawn-theme Область получает класс нарисованной темы; при настройках по умолчанию основной текст не ниже 4.5:1, приглушённый не ниже 3:1 и только крупный
drawn-with-palette-tones Эффект рисует тонами палитр, выбирая их для каждой схемы, а не ролями темы
windows-are-mask-safe Эффект с возможностью windows рисует одну непрерывную сцену за группой карточек и не полагается на то, что скрыто маской; тему эффекта получают только окна
failure-falls-back Эффект, который не смонтировался или упал, заменяется эффектом продукта по умолчанию, а сбой сообщается (sf-effect-error), а не показывается сломанной страницей
foreign-effects-sandboxed Чужой эффект работает только во фрейме без allow-same-origin, под строгой политикой безопасности содержимого, и получает настройки сообщением
pair-under-the-same-trust Пара загружается под тем же доверием, что и эффект: идентификатор сверяется с индексом каталога, чужой адрес работает только в изолированном фрейме и без него отклоняется
installed-effects-checked Эффект устанавливается только после проверки пакета — допустимые файлы, размер, манифест, отпечаток каждого файла — и выключенным, пока его не включит человек
kit-before-listing Перед показом в списке продукт прогоняет набор проверок, включая схемы, контраст, смену схемы, режим окон и доверие к паре

Стандарт опирается на правила взаимодействия компонентов в части движения и изоляции сбоев. Проверка ручная, а набор проверок меряет то, что можно измерить в браузере.

Смотрите также

Поиск по документации

Введите минимум 2 символа

    Настройки

    Тема
    Размер шрифта
    Ширина страницы