Offcanvas -- выезжающие панели
Централизованный API для работы с offcanvas-элементами (выезжающими панелями). Обеспечивает показ и скрытие панелей, swipe-функциональность и управление cookie. Панели построены на компоненте HSOverlay из Preline UI.
Доступ к API
API входит в собранный JS-бандл темы и доступен глобально после загрузки страницы:
window.waTheme.offcanvasAPI
Тема сама вызывает инициализацию при загрузке; вручную методы initOffcanvasElements() и initSwipeElements() нужно вызывать только после динамического добавления разметки.
Публичные методы
show(options)
Показывает offcanvas-панель. Может открыть существующую панель или создать новую динамически. Панель, созданная динамически, выезжает снизу (нижний лист).
Параметры (объект options):
| Параметр | Тип | Описание |
|---|---|---|
id | string | ID элемента offcanvas (обязательно) |
html | string | HTML-содержимое (если элемент нужно создать) |
className | string | Дополнительные CSS-классы |
autoOpen | boolean | Автоматически открыть (по умолчанию true) |
cookie | Object | Настройки cookie (см. ниже) |
onClose | function | Callback при закрытии |
Настройки cookie:
| Параметр | Тип | Описание |
|---|---|---|
name | string | Имя cookie |
value | string | Значение cookie |
lifetime | number | Время жизни в часах (по умолчанию 24) |
trigger | string | Когда устанавливать: 'open' или 'close' |
Возвращает: объект вида { element }, где element — экземпляр HSOverlay (методы вызываются как result.element.open()), либо undefined, если панель не найдена и не передан html.
Примеры:
Открыть существующую панель:
window.waTheme.offcanvasAPI.show({
id: 'my-offcanvas'
});
Создать и показать панель с HTML-содержимым:
window.waTheme.offcanvasAPI.show({
id: 'dynamic-offcanvas',
html: '<div class="p-4"><h3>Заголовок</h3><p>Содержимое панели</p></div>',
className: 'custom-class'
});
С настройкой cookie и callback при закрытии:
window.waTheme.offcanvasAPI.show({
id: 'promo-offcanvas',
html: '<div class="text-center p-6"><h2>Скидка 20%!</h2><p>Только сегодня</p></div>',
cookie: {
name: 'promo_shown',
value: '1',
lifetime: 48,
trigger: 'close'
},
onClose: (instance) => {
console.log('Offcanvas закрыт');
}
});
close(id)
Закрывает offcanvas-панель по ID.
window.waTheme.offcanvasAPI.close('my-offcanvas');
addSwipeToClose(target, options)
Добавляет swipe-to-close к любому offcanvas-элементу программно. target — селектор или DOM-элемент.
window.waTheme.offcanvasAPI.addSwipeToClose('#my-offcanvas', {
swipeFullElement: true,
ignoreInteractiveElements: false,
minSwipeVelocity: 1.2
});
initOffcanvasElements()
Инициализирует все offcanvas-элементы на странице, найденные по селектору [data-offcanvas].
window.waTheme.offcanvasAPI.initOffcanvasElements();
initSwipeElements()
Инициализирует swipe-функциональность для элементов с классом .hs-offcanvas-swiper.
window.waTheme.offcanvasAPI.initSwipeElements();
disconnectObserver()
Отключает MutationObserver для экономии ресурсов.
window.waTheme.offcanvasAPI.disconnectObserver();
Открытие через data-атрибут
Offcanvas-панель можно открыть через атрибут data-hs-overlay на любом кликабельном элементе:
<button type="button" data-hs-overlay="#myOffcanvas">
Открыть панель
</button>
<a href="javascript:;" data-hs-overlay="#myOffcanvas">
Открыть панель
</a>
HTML-разметка offcanvas
Для размещения панели на сайте создайте блок в приложении Сайт — Блоки site.seller2_body_html и разместите там код. Пример панели, выезжающей снизу (такую разметку используют мобильные панели темы):
<!-- Кнопка-триггер -->
<button type="button"
class="btn btn-theme btn-base"
data-hs-overlay="#myCustomOffcanvas">
Открыть панель
</button>
<!-- Offcanvas панель (выезжает снизу) -->
<div id="myCustomOffcanvas"
class="hs-overlay hs-overlay-open:translate-y-0 translate-y-full flex flex-col fixed bottom-0 inset-x-0 transition-all duration-300 transform w-full max-h-screen z-overlay-offcanvas bg-white rounded-t-2xl dark:bg-neutral-800 hs-overlay-backdrop-open:bg-neutral-900/80 hidden"
role="dialog"
tabindex="-1"
aria-labelledby="myCustomOffcanvasLabel">
<!-- Заголовок -->
<div class="flex justify-between items-center py-3 px-4 border-b dark:border-neutral-700">
<h3 id="myCustomOffcanvasLabel" class="font-bold text-gray-800 dark:text-white">
Заголовок панели
</h3>
<button type="button"
class="size-8 inline-flex justify-center items-center rounded-full bg-gray-100 text-gray-800 hover:bg-gray-200 dark:bg-neutral-700 dark:text-neutral-400 dark:hover:bg-neutral-600"
data-hs-overlay="#myCustomOffcanvas">
<span class="sr-only">Закрыть</span>
<svg class="size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 6 6 18"></path>
<path d="m6 6 12 12"></path>
</svg>
</button>
</div>
<!-- Содержимое -->
<div class="p-4 overflow-y-auto">
<p class="text-gray-800 dark:text-neutral-400">
Содержимое offcanvas-панели.
</p>
</div>
</div>
Панель, выезжающая слева:
<div id="myLeftOffcanvas"
class="hs-overlay hs-overlay-open:translate-x-0 -translate-x-full flex flex-col fixed top-0 start-0 transition-all duration-300 transform h-full w-full max-w-80 z-overlay-offcanvas bg-white border-e dark:bg-neutral-800 dark:border-neutral-700 hidden"
role="dialog"
tabindex="-1">
<div class="p-4 overflow-y-auto">
Содержимое панели
</div>
</div>
Направления выезда
| Направление | Классы |
|---|---|
| Слева | hs-overlay-open:translate-x-0 -translate-x-full fixed top-0 start-0 |
| Сверху | hs-overlay-open:translate-y-0 -translate-y-full fixed top-0 inset-x-0 |
| Снизу | hs-overlay-open:translate-y-0 translate-y-full fixed bottom-0 inset-x-0 |
В собранный CSS темы входят только перечисленные классы сдвига (-translate-x-full, -translate-y-full, translate-y-full); класса translate-x-full для выезда справа в сборке нет — при необходимости добавьте его собственным CSS.
Автоматическая инициализация через data-offcanvas
Добавьте атрибут data-offcanvas к элементу с JSON-конфигурацией для автоматической инициализации:
<div data-offcanvas='{"id": "example-offcanvas", "delay": 3}'>
<div class="p-4">
<h3>Заголовок</h3>
<p>Содержимое offcanvas</p>
</div>
</div>
Параметры data-offcanvas:
| Параметр | Тип | Описание |
|---|---|---|
id | string | ID создаваемого offcanvas-элемента |
delay | number | Задержка показа в секундах (0 = сразу, -1 = создать, но не открывать автоматически) |
remove | boolean | Удалить исходный элемент после обработки |
className | string | Дополнительные CSS-классы |
cookie | Object | Настройки cookie; если cookie уже установлена в заданное значение, панель не создаётся |
Пример: промо-панель с задержкой и cookie
<div data-offcanvas='{
"id": "promo",
"delay": 5,
"remove": true,
"cookie": {
"name": "promo_seen",
"value": "1",
"trigger": "close"
}
}'>
<div class="text-center p-6">
<h2>Скидка 20%!</h2>
<p>Только сегодня</p>
</div>
</div>
Swipe-функциональность
Для включения закрытия свайпом добавьте класс .hs-offcanvas-swiper к элементу внутри offcanvas:
<div id="my-offcanvas" class="hs-overlay ...">
<div class="hs-offcanvas-swiper" data-params='{"threshold": 100}'>
<!-- Содержимое -->
</div>
</div>
Параметры data-params
Базовые параметры:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
threshold | number | 50 | Минимальное расстояние в px для закрытия |
swipeFullElement | boolean | false | Свайп по всему offcanvas, а не только по handle |
ignoreInteractiveElements | boolean | true | Игнорировать касания интерактивных элементов |
Scroll-aware параметры:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
scrollAware | boolean | true | Умная детекция скролла vs свайпа |
minSwipeDistance | number | 30 | Минимальное расстояние свайпа в px |
maxScrollOffset | number | 10 | Макс. отступ от верха для работы свайпа в px |
minSwipeVelocity | number | 1.0 | Минимальная скорость свайпа в px/ms |
maxSwipeTime | number | 200 | Макс. время для быстрого жеста в мс |
minDistanceForVelocityCheck | number | 20 | Мин. расстояние перед анализом скорости в px |
Режимы работы свайпа
Обычный режим (scrollAware: false) — простая логика: свайп вниз больше threshold = закрытие.
<div class="hs-offcanvas-swiper" data-params='{"threshold": 50, "scrollAware": false}'>
<!-- Простой контент -->
</div>
Scroll-aware режим (scrollAware: true, по умолчанию) — умная детекция намерений пользователя:
- Первые 20px движения — offcanvas не двигается, работает только скролл
- После 20px — анализ скорости и времени жеста
- Быстрый жест (< 200ms, > 1.0 px/ms) — offcanvas начинает двигаться
- Медленное движение — продолжается обычный скролл
- При завершении — закрытие только для быстрых жестов
<div class="hs-offcanvas-swiper" data-params='{
"threshold": 50,
"swipeFullElement": true,
"minSwipeVelocity": 1.2,
"maxSwipeTime": 150
}'>
<!-- Контент с возможностью скролла -->
</div>
Программное создание offcanvas
Полный пример создания offcanvas-панели через JavaScript:
// Создать и показать offcanvas с содержимым
window.waTheme.offcanvasAPI.show({
id: 'cart-summary',
html: `
<div class="p-4">
<h3 class="font-bold text-lg mb-4">Корзина</h3>
<div class="hs-offcanvas-swiper">
<p>Содержимое корзины</p>
</div>
</div>
`,
onClose: () => {
console.log('Корзина закрыта');
}
});
// Позже закрыть
window.waTheme.offcanvasAPI.close('cart-summary');
События
Offcanvas поддерживает события HSOverlay:
const offcanvasEl = document.querySelector('#myCustomOffcanvas');
offcanvasEl.addEventListener('open.hs.overlay', () => {
console.log('Панель открыта');
});
offcanvasEl.addEventListener('close.hs.overlay', () => {
console.log('Панель закрыта');
});