Skip to main content
Пользовательский шаблон позволяет переопределить отображение отдельного блока. Вместо встроенного интерфейса блока корзина отображает ваш собственный JSX, используя те же данные, которые блок использовал бы обычно. Это сквозная возможность, а не отдельный блок: большинство блоков предоставляют её на своей вкладке Code. Эта страница описывает то, что относится к каждому блоку. Пропсы конкретного блока смотрите в справочнике самого блока.

Пользовательский шаблон и блок Custom code

Звучат похоже, но делают разные вещи:
  • Пользовательский шаблон заменяет отображение существующего блока вашей собственной разметкой и передаёт вам данные этого блока (заголовок и счётчик товаров у Header, итоги у Summary и так далее). Он не добавляет ничего нового; он переоформляет один блок.
  • Блок Custom code добавляет новый блок произвольного HTML или React в любое место корзины.
Берите пользовательский шаблон, когда встроенный блок почти подходит, но вам нужен другой макет или разметка. Берите блок Custom code, когда хотите добавить что-то, чего встроенные блоки не покрывают.

Использование пользовательского шаблона

  1. Выберите блок в редакторе и откройте его вкладку Code.
  2. Отредактируйте шаблон по умолчанию. Пользовательские шаблоны — это только JSX (выбор HTML-или-JSX есть только у блока Custom code).
  3. Нажмите Compile. Компиляция удаляет типы и транспилирует JSX, поэтому она ловит синтаксические ошибки. Ошибки типов компиляцию не останавливают — редактор подсвечивает их по мере ввода тем же IntelliSense, который автодополняет пропсы блока.
  4. Включите шаблон, чтобы корзина использовала его вместо встроенного отображения.
  5. Reset to default в любой момент восстанавливает исходный шаблон блока.

Написание шаблона с помощью ИИ

Вкладка Code включает кнопку Copy AI prompt (значок волшебной палочки ✦). Её нажатие копирует в буфер обмена самодостаточное задание, которое можно вставить прямо в сессию ИИ-чата (Claude, ChatGPT или аналог). Промпт включает всё, что нужно ИИ для написания корректного шаблона именно для этого блока:
  • Правила компиляции (одно выражение, без export default, без импортов)
  • Точные пропсы, которые получает блок, совпадающие с тем, что показывает IntelliSense редактора
  • Заблокированную сигнатуру функции, которую требует редактор
  • Специфичные для блока правила (денежные форматы, какие обработчики подключать, требования доступности)
  • Раздел для заполнения, куда вы вставляете свой текущий шаблон и описываете желаемое изменение
После копирования откройте сессию ИИ, вставьте промпт, заполните два пропуска внизу (ваш текущий шаблон и желаемое изменение) и отправьте. ИИ вернёт готовый шаблон, который вы можете вставить обратно в редактор и скомпилировать.
Вставляйте свой существующий шаблон в раздел для заполнения, а не оставляйте его пустым. ИИ использует его как отправную точку, поэтому все уже сделанные вами настройки переносятся, а не заменяются шаблоном по умолчанию.
Промпт специфичен для каждого блока. Кнопка Copy AI prompt появляется только на блоках, поддерживающих пользовательские шаблоны.
Шаблон по умолчанию, с которого вы начинаете, — это рабочая копия встроенной разметки блока, поэтому у вас всегда есть корректный, отображающийся образец для изменения, а не пустая страница. Используйте Reset to default, когда захотите вернуть этот образец.Он не всегда совпадает байт в байт. Шаблон Header по умолчанию также отображает logoUrl, для которого во встроенной разметке нет места, поэтому включение этого шаблона — это способ впервые показать загруженное изображение заголовка.

Что заменяет ваш шаблон

Шаблон заменяет отображение блока полностью. Вокруг вашего JSX не остаётся обёртки, что имеет последствия, о которых стоит знать, прежде чем начинать что-то удалять:
Вкладка Design — это то, на чём чаще всего попадаются. Пока пользовательский шаблон активен, поля вкладки Design отключены, а рядом с заголовком «Design» появляется значок предупреждения. Наведите на значок, чтобы узнать причину. Вместо этого оформляйте блок из своего шаблона, инлайн или собственным CSS. Поля снова включаются, как только вы выключаете пользовательский шаблон.
Что вы сохраняете: позицию блока в корзине, его переключатель видимости, его настройки (которые по-прежнему питают получаемые вами пропсы), панель пользовательского CSS корзины и встроенный скелетон загрузки. Последнее удивляет людей. Блок проверяет, загружается ли ещё корзина, до обращения к вашему шаблону, поэтому встроенный скелетон отображается во время загрузки, а ваш шаблон выполняется только после готовности корзины. Вам не нужно создавать состояние загрузки.

Что доступно внутри шаблона

Ваш шаблон — это один функциональный компонент. Он компилируется из TSX, поэтому аннотации типов допустимы и удаляются при компиляции. Именно поэтому шаблоны по умолчанию написаны с ними:
Строка сигнатуры и закрывающая скобка заблокированы — редактор не позволит редактировать ни то, ни другое, а при наведении показывается «Locked — this line can’t be edited.» Вы пишете тело между ними. Reset to default — единственное, что может их заменить. Что ещё важно:
  • Вам доступны пять хуков: useState, useEffect, useMemo, useRef и useCallback. Плюс Fragment для <>…</>.
  • Импортов нет. Вы не можете ничего import, и в области видимости нет объекта React, поэтому никаких React.useReducer, React.Children. Если хука нет в списке выше, он недоступен.
  • Пропсы доступны только для чтения. Мутирование пропа не даст ничего полезного. Чтобы изменить корзину, используйте пропсы-обработчики, которые даёт блок (onClose, increment, selectPlan и так далее), а не запись в пропсы напрямую.
  • window доступен, поэтому шаблон может обращаться к Cart SDK через window.aftersell.cart, когда нужно что-то, чего пропсы блока не покрывают.

Соглашения для всех блоков

Три правила действуют везде, и знание их избавляет от большинства догадок:
  • Пропсы *Html — это предварительно очищенный форматированный текст. Отображайте их через dangerouslySetInnerHTML. Они уже прошли через санитайзер корзины, а токены мерчанта вроде {{total_price}} уже подставлены.
  • Цены, приходящие как string, уже отформатированы в денежном формате магазина. Цены как number — в центах. Блок даёт вам либо одно, либо другое, и таблица каждого блока указывает, что именно.
  • isLoading внутри шаблона всегда false. Блок отображает встроенный скелетон и вызывает ваш шаблон только после загрузки корзины, поэтому проп передаётся для полноты, а не для ветвления.
Несколько блоков в определённых состояниях вообще ничего не возвращают, поэтому ваш шаблон никогда не вызывается с пустыми данными. Шаблон Rewards никогда не видит пустой milestones, а шаблон Subscription upgrade никогда не видит view равный null. Справочник каждого блока отмечает, где это применяется, чтобы вы могли пропустить ветку пустого состояния.

Оформление пользовательского шаблона

Шаблон по умолчанию, с которого вы начинаете, несёт имена классов блока. Как оформлять ваши правки, зависит от того, насколько далеко вы уходите от этой отправной точки.

Два семейства классов

Каждый элемент в шаблоне по умолчанию несёт парное имя класса, и они выполняют очень разные задачи: Итак, cart-internal-header__title — это то, что делает заголовок похожим на встроенный, а cart-external-header__title — рукоятка, за которую нужно браться, когда вы хотите изменить его вид.

Небольшие изменения: сохраните оба имени класса

Если вы переставляете элементы, переименовываете или добавляете что-то внутри существующей структуры, оставьте имена классов в покое. Вы бесплатно сохраняете встроенный вид, а переоформляете через пользовательский CSS, нацеливаясь на хуки cart-external-*.

Перестройка: уберите оба имени класса

Как только вы меняете структуру DOM, а не подправляете её, уберите оба семейства из вашей разметки и используйте собственные имена классов. Для каждого есть своя причина. Уберите cart-internal-*, потому что встроенный CSS написан для встроенного DOM. Оставите эти классы на перестроенной разметке — и унаследуете правила макета, предполагающие элементы, которых у вас больше нет: flex-контейнеры, ожидающие других детей, интервалы между переместившимися элементами, позиционирование относительно того, что вы удалили. Обычно это проявляется как ваш CSS, который «не работает», когда на самом деле побеждают встроенные правила.
Уберите cart-external-*, потому что это общее имя, а не ваше. Эти имена классов означают что-то конкретное во встроенной разметке, а ваш Custom CSS пишется один раз для всей корзины. Если перестроенный шаблон их переиспользует, любое написанное вами правило нацеливается и на вашу структуру, и на встроенную.Это ломается в момент выключения пользовательского шаблона: блок возвращается к встроенной разметке, а ваш CSS всё ещё указывает на неё, теперь оформляя DOM, для которого никогда не был написан. Собственный префикс чётко разделяет эти два случая, поэтому выключение шаблона — это чистый откат.
Два способа оформить то, что вы построили:

Вариант 1: собственные имена классов плюс Custom CSS

Лучше всего для всего, что вы будете поддерживать или переиспользовать. Дайте своим классам префикс, с которым никто не столкнётся, обычно имя вашего магазина или бренда:
Затем в редакторе корзины выберите Cart settings в левой панели и откройте вкладку Custom CSS справа:
Префикс важнее, чем кажется. Без него класс вроде .header или .title рискует конфликтовать с собственными классами корзины, шаблоном другого приложения или будущим блоком.

Вариант 2: инлайн-стили

Без похода в панель CSS, и всё живёт в одном месте:
Хорош для каркаса макета и разовых случаев. Его ограничения — обычные: нет :hover и других псевдоклассов, нет медиазапросов и нет переиспользования между блоками. Переходите к варианту 1, когда понадобится что-то из этого.

Выбор подхода

Корзина отображается в shadow root, поэтому таблица стилей вашей темы не может проникнуть внутрь. Стили для пользовательского шаблона должны идти из собственной панели Custom CSS корзины или из инлайн-стилей, а не из вашей темы. См. Пользовательский CSS.

Когда шаблон ломается

Сломанный шаблон никогда не ломает корзину. Блок отображает ничего, а всё вокруг него продолжает работать, что безопасно, но легко упустить: пустое место там, где должен быть ваш блок, — вот симптом. Поскольку блок молча исчезает, а не выдаёт видимую ошибку, всегда проверяйте шаблон в предпросмотре перед публикацией. Если блок пропал, сначала откройте консоль браузера. Две вещи, от которых стоит защищаться, поскольку обе роняют шаблон, предполагающий обратное:
  • Пропсы, допускающие null. Многие пропсы равны null в нормальных условиях (logoUrl без логотипа, imageUrl без изображения, variantTitle у товара с одним вариантом). Проверяйте перед использованием.
  • Массивы, которые могут быть пустыми. discountTags и discountCodes гораздо чаще равны [], чем нет.

Ограничения

  • Пользовательские шаблоны — это переопределения отображения. Чтобы выполнять логику для корзины (подписываться на события, добавлять товары, реагировать на изменения), используйте пользовательские скрипты и Cart SDK.
  • Почти каждый блок его поддерживает. Исключения — блок Express payments, который содержит собственные платёжные кнопки Shopify, и сам контейнер Cart items, хотя строка Product внутри него пользовательский шаблон поддерживает.
  • Шаблон не может изменить то, что блок делает по существу. Он меняет то, как представлены данные блока, а не сами данные или поведение за ними.

Пропсы каждого блока

Каждый блок передаёт собственные данные. Полная таблица пропсов с типами и рабочим примером находится на странице этого блока: Блок Custom code — единственная поверхность, которая добавляет разметку, а не заменяет отображение блока, поэтому его пропсы другие: вся корзина плюс действие добавления в корзину. См. Блоки пользовательского кода → Пропсы.