Розробникам · Теми
Поведінки й стилі
Меню, шухляди, вкладки, каруселі й банери без власного JavaScript — атрибутами data-sf-*. Що лишає санітайзер, іконки масками, змінні дизайну --store-* і стилізація компонентів ядра.
Секції теми працюють без власного JavaScript: вивід проходить санітайзер, а меню, шухляди, вкладки й каруселі вмикає скрипт ядра за атрибутами data-sf-*. Він знає клавіатуру, Esc, тач і aria-expanded, працює після оновлень Livewire і поважає prefers-reduced-motion. Власний JavaScript теми працює на власному домені магазину (на адресі storeforma.shop — лише в офіційних темах без змін), тож тема має працювати й без нього.
Поведінки data-sf-*
| Атрибут | На чому | Що робить |
|---|---|---|
| data-sf-disclosure | корінь | Обгортка кнопки й панелі; відкритий корінь отримує data-sf-open. |
| data-sf-disclosure-trigger | button | Відкриває й закриває панель з aria-controls або панель свого кореня; ставить aria-expanded. Стрілка вниз відкриває панель з клавіатури. |
| data-sf-disclosure-panel | панель | Панель з hidden у розмітці. Відкриття однієї закриває інші, крім тих, що її містять; Esc і клік поза панеллю закривають (шухляду — лише Esc і data-sf-close). |
| data-sf-hover | корінь | Відкривати при наведенні мишею: коротка затримка на відкриття, довша — на закриття. Лише миша; на тачі — кліком. |
| data-sf-drawer | панель | Шухляда: поки відкрита, сторінка не прокручується; Esc закриває останню. |
| data-sf-close | button | Закриває свою панель чи шухляду або ховає свій банер data-sf-dismiss. |
| data-sf-sticky="40" | шапка | Після прокрутки на 40 px (8 за замовчуванням) ставить data-sf-scrolled="true", інакше "false". |
| data-sf-carousel="5000" | корінь | Показує дочірні data-sf-slide по черзі, кожні 5000 мс (не менше 2000); пауза при наведенні й фокусі; без руху при reduced motion. |
| data-sf-slide | слайд | Один слайд каруселі; решта отримують hidden. |
| data-sf-dismiss="spring-sale" | банер | Банер, який відвідувач закриває кнопкою data-sf-close; браузер памʼятає це за ключем. |
| data-sf-scroller | корінь | Стрічка з кнопками гортання. |
| data-sf-scroller-track | стрічка | Що гортати; без неї — сам корінь. Прокрутку задає ваш CSS (overflow-x: auto, scroll-snap). |
| data-sf-scroll="prev|next" | button | Гортає стрічку на ~90 % видимої ширини. |
| data-sf-tabs | корінь | Група вкладок. |
| data-sf-tab | button | Показує панель зі свого aria-controls, ховає інші панелі групи й ставить собі aria-selected="true"; сторінка не стрибає. |
<div class="bloom-item" data-sf-disclosure data-sf-hover>
<a href="{{ link.url }}">{{ link.title }}</a>
<button data-sf-disclosure-trigger aria-expanded="false" aria-controls="bloom-sub-{{ forloop.index }}" aria-label="{{ link.title }}">▾</button>
<div id="bloom-sub-{{ forloop.index }}" data-sf-disclosure-panel hidden>…</div>
</div>
<button data-sf-disclosure-trigger aria-controls="bloom-drawer" aria-expanded="false">{{ 'ui.main_menu' | t }}</button>
<div id="bloom-drawer" data-sf-disclosure-panel data-sf-drawer hidden>
<button data-sf-close aria-label="{{ 'ui.prev' | t }}">×</button> …
</div>
<header data-sf-sticky="40">…</header>
<div data-sf-tabs>
<button data-sf-tab aria-controls="tab-a" aria-selected="true">…</button>
<button data-sf-tab aria-controls="tab-b" aria-selected="false">…</button>
<div id="tab-a">…</div><div id="tab-b" hidden>…</div>
</div>
<div data-sf-scroller>
<div class="bloom-strip" data-sf-scroller-track>…картки…</div>
<button data-sf-scroll="prev" aria-label="{{ 'ui.prev' | t }}">‹</button>
<button data-sf-scroll="next" aria-label="{{ 'ui.next' | t }}">›</button>
</div>- Стилізуйте за станом: відкрита панель — без , кнопка — , корінь — , шапка — , вкладка — .
- Покрокове мобільне меню — вкладені панелі в шухляді з кнопкою «Назад» .
- Без JavaScript панель закрита: пункт з підменю має бути й посиланням на свою сторінку. Перша вкладка відкрита в розмітці, решта — з .
- Інші атрибути вирізаються.
Що лишає санітайзер
У звичайному (захищеному) режимі вивід секцій і сніпетів проходить санітайзер. Компоненти ядра вставляються після нього й не чіпаються.
| Лишається | Вирізається |
|---|---|
| Звичайні елементи HTML: розмітка, текст, списки, таблиці, a, img, picture і source, video, button, details і summary, dialog | script, iframe, svg (разом з вмістом), form, input, власні елементи |
| Атрибути class, id, style, role, title, lang, dir, hidden, loading, width, height, sizes, srcset, alt, href, src, target, rel | Обробники on*= і атрибути Alpine (x-data, @click, :class) |
| aria-label, aria-hidden, aria-describedby, aria-expanded, aria-controls, aria-haspopup, aria-current, aria-labelledby, aria-selected | data-* поза переліком data-sf-* вище |
| Посилання https, mailto, tel і відносні; фото й відео https і відносні | Посилання http:, javascript:, data: та інші схеми |
| <style> і style="…" — після очищення CSS | @import, expression(), url() на інші сайти |
CSS у файлах теми, у <style> і {% stylesheet %} очищується тими самими правилами: url() лишається лише для шляхів магазину й файлів теми.
Іконки
Inline SVG вирізається. Іконка — файл у assets/, який CSS малює маскою в кольорі тексту чи акценту. Відносна адреса в CSS теми вказує на файл тієї самої теми:
/* assets/theme.css */
.bloom-ico::before { content: ""; display: inline-block; width: 1.25rem; height: 1.25rem; background: currentColor;
-webkit-mask: var(--bloom-ico) center / contain no-repeat; mask: var(--bloom-ico) center / contain no-repeat; }
.bloom-ico--truck { --bloom-ico: url("icon-truck.svg"); }
{# у секції #}
<span class="bloom-ico bloom-ico--truck" aria-hidden="true"></span>В атрибуті src картинки — фільтр asset_url: <img src="{{ 'logo.svg' | asset_url }}" alt="…">. Іконки пунктів меню дає саме меню: link.icon_svg (іконка ядра) і link.icon_url (власна іконка власника).
Змінні дизайну --store-*
Кольори, шрифти, заокруглення й відступи власник змінює в «Стилях магазину». Тема, що пише лише змінні, змінюється разом з ними без жодної правки коду.
| Змінна | Що |
|---|---|
| --store-paper | Фон сторінки. |
| --store-surface | Фон карток і панелей. |
| --store-ink | Основний текст. |
| --store-muted | Другорядний текст. |
| --store-primary, --store-primary-strong, --store-primary-soft | Основний колір, темніший і світлий відтінки. |
| --store-accent | Акцент: знижки, лічильники, кнопки дії. |
| --store-on-accent | Текст на акценті. |
| --store-on-dark | Текст на темному фоні (#ffffff). |
| --store-primary-rgb, --store-primary-strong-rgb, --store-primary-soft-rgb, --store-accent-rgb | Ті самі кольори трійкою для прозорості: rgb(var(--store-primary-rgb) / 0.2). |
| --store-radius | Базовий радіус. |
| --store-radius-sm, -md, -lg, -xl | ×0,5, ×0,75, ×1,5, ×2 від базового; базовий 0 — квадратно всюди. |
| --store-radius-full | 9999px (0 для квадратного дизайну) — пігулки й кружечки. |
| --store-font-sans, --store-font-display | Шрифт тексту й заголовків. |
| --store-text-xs, -sm, -base, -lg, -xl, -2xl, -3xl, -4xl, -5xl | Розміри тексту 0,75–3 rem; уся шкала росте чи меншає з налаштуванням розміру тексту. |
| --store-space-0 … --store-space-28 | Відступи: 0, 0-5, 1, 1-5, 2, 2-5, 3, 3-5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28 (крок 1 = 0,25 rem). |
| --store-shadow-card | Тінь картки або none. |
| --store-container | Ширина контейнера (88rem за замовчуванням). |
Одна тінь і один радіус на тему через ці змінні. Фіксовані кольори лишайте для власних акцентів, яких немає серед токенів.
Вибір власника в дизайні стоїть атрибутами на <html>: data-sf-headings (normal, caps), data-sf-weight (regular, light), data-sf-nav (normal, caps), data-sf-catalog-columns (3, 4, 5), data-sf-catalog-filters (sidebar, sidebar-right, top, drawer), data-sf-catalog-header (default, minimal, centered), data-sf-catalog-options (list, chips, swatches), data-sf-catalog-pagination (pages, more), data-sf-catalog-gap (theme, lines, small, medium, large). CSS теми може на них спиратися. Свій відступ між картками тема задає лише для «Як у темі»: [data-sf-catalog-gap="theme"] .store-product-grid { gap: 1.5rem; } — тоді вибір власника його перекриває. Стилі Storeforma лежать у каскадних шарах, тож будь-яке правило теми їх перекриває без !important; лише приховані панелі ([hidden]) лишаються прихованими.
Стилізація компонентів ядра
Розмітку навколо компонента пишете вільно. Сам компонент стилізуйте трьома способами — вони контракт; класи й вкладеність усередині компонента можуть змінюватися.
- Обгортка — , : кожен компонент має атрибут зі своїм типом.
- Частини — всередині компонента.
- Змінні на обгортці теми.
| Змінна | Де діє |
|---|---|
| --sf-menu-gap | Відстань між пунктами header.menu (1.5rem). |
| --sf-menu-link-color, --sf-menu-link-hover-color | Пункти верхнього рівня. |
| --sf-panel-bg, --sf-panel-shadow | Список, що випадає. |
| --sf-mega-panel-bg, --sf-mega-panel-shadow | Панель мегаменю. |
| --sf-badge-radius, --sf-badge-{accent,sale,muted}-{bg,color} | Бейджі пунктів меню. |
| --sf-cart-count-bg, --sf-cart-count-color | Лічильник кошика. |
| --sf-wishlist-count-bg, --sf-wishlist-count-color | Лічильник обраного. |
| --sf-announcement-bg, --sf-announcement-color | header.announcement. |
| --sf-footer-title-color, --sf-footer-link-color, --sf-footer-link-hover-color | Колонки підвалу. |
| --store-footer-background | Тло підвалу разом зі смугою Storeforma під ним; тема, що фарбує підвал своїм кольором, задає його тут у :root. |
| --store-footer-credit-color, --store-footer-credit-line | Текст і лінія смуги Storeforma — для світлого підвалу. |
| Частини data-sf-part | Де |
|---|---|
| menu-bar, link, trigger, panel, menu-image, menu-badge (з data-tone), menu-icon | Меню шапки. |
| mega-panel (з data-kind), mega-columns, mega-column, mega-group, mega-tiles, mega-tile, mega-tabs, mega-tab, mega-tab-panel, mega-aside, mega-below, mega-layout-column, mega-carousel, mega-step | Мегаменю. |
| catalog-panel, catalog, catalog-list, catalog-item, catalog-detail, catalog-item-panel | Кнопка «Каталог» і відкрите меню каталогу. |
| icon, label, count (data-sf-count = badge або inline) | Кнопки-дії шапки. |
| message, close | Оголошення. |
| title, image, button, phone, email, hours, telegram | Банери й контакти. |
| catalog-header, toolbar, filter-bar, filter-pop, filter-pop-button, filter-panel, filter-group, filter-button, filter-drawer, sidebar, grid, load-more | Каталог і фільтри; також класи sf-filter-option і sf-catalog-title. |
.bloom-header { --sf-menu-gap: 2rem; --sf-cart-count-bg: var(--store-ink); --sf-mega-panel-shadow: none; }
.bloom-header [data-sf-part="menu-badge"][data-tone="sale"] { letter-spacing: .1em; }
.bloom-product [data-component="product.price"] { font-size: var(--store-text-2xl); }Внутрішню розмітку мінікошика й рядків кошика тема не замінює — лише стилізує. Вигляд компонента в цілому (варіант кнопки, пропорції фото, вигляд вибору варіанта) задає дизайн магазину; з Liquid можна обрати один з його іменованих стилів: {% component 'product.gallery', style: 'square' %}.
Нижня панель на телефоні
Панель mobile.nav стоїть унизу екрана на телефоні; пункти (home, catalog, filters, search, wishlist, cart, account — до пʼяти) обирає власник у «Налаштування сайту». Тема її не малює, а фарбує змінними:
| Змінна | Що |
|---|---|
| --sf-mobile-nav-bg | Фон. |
| --sf-mobile-nav-color | Текст і іконки. |
| --sf-mobile-nav-border, --sf-mobile-nav-shadow | Лінія й тінь зверху. |
| --sf-mobile-nav-active | Пункт поточної сторінки. |
| --sf-mobile-nav-count-bg, --sf-mobile-nav-count-color | Лічильники кошика й обраного. |
Частини: item (з data-item — назва пункту, у поточного aria-current="page"), label, count. Вітрина сама лишає під панель місце внизу сторінки. Перевіряйте телефон 390 px: власні фіксовані елементи теми (кнопка «Нагору», липка панель) не мають ховатися під нею.