GriffinJS

Опциональный слой виджетов с состоянием: слайдер, галерея, лайтбокс, параллакс, мегаменю. Один файл, одна строка подключения; страница без него — законное и рабочее состояние.

Опциональный слой packages/ui/dist/griffinjs.js packages/ui/dist/griffinjs.css

Обзорная страница слоя. Семейство прокрутки — страница «Слайды»: дорожка, слайдер, галерея, лайтбокс, движок fade, — параллакс и семейство выпадающего: мегаменю плюс контроллеры дропдауна и подсказки на странице «Слои поверх страницы», — и окна и комбобокс; закраску ползунка и пару «от — до» слой добавляет форме — «Формы», а сортировку строк — таблице: «Таблицы». Расширенные поля форм — маска, телефон, дата, файл, оценка, одноразовый код, счётчик и сводка ошибок — лежат вторым файлом, «Поля форм»: простой проект за них не платит. Устройство слоя — на странице «Архитектура».

Подключение

Слой лежит внутри пакета griffincss-ui и подключается одной строкой после стилей. У него свой глобал — window.GriffinJS, отдельный от window.Griffincss; от рантаймов ядра, компонентов и утилит он не зависит и работает при подключённом одном CSS.

<link rel="stylesheet" href="griffincss-ui.css">
<link rel="stylesheet" href="griffinjs.css">
<script defer src="griffinjs.js"></script>

defer — потому что до первой отрисовки слою ставить нечего: разметка до его старта живёт базой без скрипта, а в блокирующем пути остаются только тема и раскладки («Что в <head>, что defer»). Стартует слой, когда поставка зарегистрирована целиком: отложенный тег — на DOMContentLoaded, после всех defer-тегов, включая griffinjs-fields.js и griffinjs-countries.js; тег, вставленный скриптом в готовый документ, — сразу после своего файла. Набор «ядро + нужное», вставляемый скриптом по одному тегу, поднимают вручную: data-auto="false" на теге ядра и GriffinJS.start() после последнего модуля. Атрибут data-auto="false" отключает автозапуск — как у остальных рантаймов библиотеки; data-fields и data-countries называют пути второго бандла, который слой догрузит сам, встретив первое поле («Догрузка по потребности»).

Слой поднимает и снимает виджеты сам, по MutationObserver, и ему всё равно, кто вставил узел. Поэтому пакетов-обёрток под React и Vue нет и не планируется: их работу делает сканер. Что при этом нужно знать — оговорки жизненного цикла и готовый хук — на странице «Griffincss в React и Vue».

Два рода вещей

Документация различает новые виджеты и контроллеры. У новых виджетов — слайдера, галереи, лайтбокса, параллакса, мегаменю, комбобокса — своя разметка и свои стили в griffinjs.css; как компонентов ui их не существует, и описываются они только в этом разделе. Контроллеры — модалка, панель, дропдаун, подсказка, ползунок, сортируемая таблица — ничего не меняют в разметке существующих компонентов: скрипт добавляет к ним атрибуты и поведение, а описание живёт на странице компонента в подразделе «С подключённым griffinjs.js».

С griffinjs.js и без

Каждый виджет обязан иметь «базу без JS». Матрица заполняется по мере появления виджетов; сейчас в ней только то, что уже решено планом.

ВиджетС griffinjs.jsБаза без JS
Дорожкаклавиатура, aria-current/inert, --gr-progress, griffin:changescroll-snap-дорожка
Слайдерточки, кнопки, автоплей с паузой, циклscroll-snap-дорожка; органы управления скрыты
Галереяпревью ведут дорожку и следуют за нейдве дорожки без синхронизации
Лайтбокс<dialog> + дорожка, группы по атрибуту, видео и iframeссылка на большое изображение
Параллакс--gr-progress на любом блоке; рецепты эффектов в CSSстатичный блок (запасное значение в var())
Движок fadeстопка слайдов, переход прозрачностью, следование за пальцемпервый слайд
Мегаменюнаведение с задержкой намерения и безопасным треугольником, одна открытая панель, клавиатура disclosure navigation, ajax-панели, закрытие с анимацией темы (closing), аккордеон на узком экране.gr-navbar + <details> в пунктах .gr-nav: щелчок раскрывает панель, CSS кладёт её под полосу
Дропдаун контроллерроли меню, клавиатура menu button, Esc и щелчок мимо для <details>, закрытие с анимацией темы (closing), позиция popover-панели без anchor positioning, наведение с задержкой.gr-dropdown как есть: <details>, popover или наведение из ui
Окна контроллерdata-gr-open, стек, блокировка прокрутки под окном (и на iOS), остановка видео, ajax-содержимое, hash с кнопкой «Назад», плавный рост окна по grow.gr-modal / .gr-drawer как есть: showModal() и <form method="dialog">
Комбобоксроли combobox/listbox, aria-activedescendant, дебаунс, отмена запроса, кеш, группы, подсветка, выборобычное поле в форме поиска
Ползунок контроллердоля пройденного пути — след до ручки красит CSS; пара «от — до» держит порядок значений, шлёт griffin:change и параметром fields связывается с числовыми полями.gr-range как есть: ползунок работает, следа нет (в Firefox есть — его рисует платформа)
Сортируемая таблица контроллеркруг aria-sort «нет → по возрастанию → по убыванию», стабильная перестановка строк, числа и ISO-даты числами, остальное — Intl.Collator с локалью документа, клавиатура на заголовке.gr-table как есть: порядок строк тот, что пришёл с сервера; указатель направления рисуется из aria-sort и без скрипта
Подсказка контроллерверхний слой (popover) по наведению с задержкой и по фокусу, позиция у якоря, Esc.gr-tooltip-anchor как есть: :hover и :focus-within из ui
Второй бандл — поля форм (griffinjs-fields.js, в griffinjs.js не входят)
Маскаформат токенами, литералы, каретка, подсказка и inputmode из формата<input pattern inputmode> — проверяет платформа
Телефонмаска по коду страны, имя и флаг от платформы, полный номер с плюсом выбирает страну; таблица стран отдельным файломtype="tel" и <select> кодов
Дата и времяна указателе мыши — маска по локали, календарь, ISO в спутнике, проверка границ; на тач-устройстве — ничего; пара «с — по» атрибутом to — границы друг друга и отрезок в панелинативный <input type="date">
Суммаразряды и дробь по локали на экране, число в спутнике, каретка держится за цифрой, границы через спутниктекстовое поле — сервер получает набранное
Файлсписок выбранного, удаление по одному через DataTransfer, накопление<input type="file" multiple>
Ввод оценки--gr-rating и слово в aria-label, наведение, подписи поверх знаковпять радиокнопок в <fieldset>
Одноразовый кодфокус по ячейкам, вставка и автозаполнение раскладываются, griffin:completeряд ячеек maxlength="1"
Счётчик символовостаток к maxlength с aria-live, состояния у порогаmaxlength действует сам
Сводка ошибокнепройденные поля ссылками с сообщениями платформы, фокус на первой, aria-invalidпузырь браузера

Модульная сборка

Кроме griffinjs.js целиком в dist/ лежат griffinjs-core.js, по файлу на общую часть — дорожка track, анимация motion, жест gesture, медиазапросы media, позиционирование у якоря anchor — и по файлу на каждый движок и виджет. В ядре осталось только то, без чего не обходится ни один виджет; всё остальное подключается после него и лишь тем, кому нужно. Размеры по модулям — на странице «Архитектура».

Весь слой одним файлом — 19,2 КБ gzip. Но берут его обычно не целиком: ядро, нужное любому набору, весит 2,8 КБ, а остальное подключается по потребности. Каждый модуль объявляет, что берёт из ядра, и таблица собрана из этих объявлений при сборке — разойтись с кодом ей нечем.

ВиджетПодключить после griffinjs-core.jsНабор целиком
data-gr-trackgriffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js6,6 КБ
data-gr-slidergriffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js + griffinjs-slider.js7,7 КБ
data-gr-gallerygriffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js + griffinjs-slider.js + griffinjs-gallery.js8,1 КБ
data-gr-lightboxgriffinjs-motion.js + griffinjs-track.js + griffinjs-scroll.js + griffinjs-lightbox.js7,9 КБ
data-gr-parallaxgriffinjs-motion.js + griffinjs-parallax.js3,6 КБ
data-gr-megamenugriffinjs-media.js + griffinjs-megamenu.js5,0 КБ
data-gr-dropdowngriffinjs-anchor.js + griffinjs-dropdown.js5,0 КБ
data-gr-tooltipgriffinjs-anchor.js + griffinjs-tooltip.js3,9 КБ
data-gr-dialoggriffinjs-dialog.js4,4 КБ
data-gr-comboboxgriffinjs-combobox.js5,3 КБ
data-gr-rangegriffinjs-range.js3,5 КБ
data-gr-sortablegriffinjs-sortable.js3,6 КБ

Порядок тегов свободный, кроме одного: griffinjs-core.js идёт первым — он создаёт window.GriffinJS. Если в наборе чего-то не хватает, слой скажет об этом в консоли при старте, а не молча недоработает: GriffinJS: «dropdown» не работает без griffinjs-anchor.js.

<script src="griffinjs-core.js"></script>
<script src="griffinjs-anchor.js"></script>
<script src="griffinjs-media.js"></script>
<script src="griffinjs-dropdown.js"></script>
<script src="griffinjs-megamenu.js"></script>

Полигон

Страница-полигон собирает все виджеты слоя на одном экране. Её проверяют браузерные тесты на трёх движках — и второй раз с отключённым скриптом: каждый пример без бейджа «нужен griffinjs.js» обязан работать и так.