-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
👋🏻
I like building compositions from primitives, e.g. a simple text and image section can be quickly thrown together right now in Liquid like:
{% capture content %}
{% render 'element.text', as:'h2', variant: 'heading-xl', slot: 'Welcome to composable Liquid theme components' %}
{% render 'element.text', variant: 'rte', slot: '<p>You can compose consistent, high-quality storefronts using well-engineered Liquid components</p>' %}
{% endcapture %}
{% capture content_stack %}
{% render 'layout.stack', gap: 'md', slot: content %}
{% endcapture %}
{% capture columns %}
{% render 'element.image' %}
{{ content_stack }}
{% endcapture %}
{% capture grid %}
{% render 'layout.grid', columns_xs: 1, columns_md: 2, gap: 'lg', slot: columns %}
{% endcapture %}
{% render 'layout.section', slot: grid %}This approach works, but I'm sure we can all agree the syntax is 💩
It would be great if snippets came with a default slot tag, so I could instead write something like this:
{% render 'layout.section' %}
{% render 'layout.grid', columns_xs: 1, columns_md: 2, gap: 'lg' %}
{% render 'element.image', img: section.settings.image %}
{% render 'layout.stack', gap: 'md' %}
{% render 'element.text', as:'h2', variant: 'heading-xl' %}
Welcome to composable theme components
{% endrender %}
{% render 'element.text', variant: 'rte' %}
<p>You can compose consistent, high-quality storefronts using well-composed Liquid components</p>
<a href="#">Click here to learn more</a>
{% endrender %}
{% endrender %}
{% endrender %}
{% endrender %}where layout.stack.liquid:
<div class="flex flex-col">{{ children }}</div>and element.text.liquid:
<{{ as }}>{{ children }}</{{ as }}>However, from my conversations with @karreiro and @charlespwd, adding an {% endrender %} tag would be a complex and potentially breaking change. We already have other way's of rendering snippets, ie. {% include %}, so what's one more way, right?
Following in suit with {%- ... -%} and {% # ... %} symbol identifiers that have already been introduced, I propose a new tag that emulates an existing open and close pattern most devs are already familiar with,
{%< ... >%}...{%</ ... >%}:
{%< 'layout.section' >%}
{%< 'layout.grid', columns_xs: 1, columns_md: 2, gap: 'lg' >%}
{%< 'element.image', img: section.settings.image >%}
{%< 'layout.stack', gap: 'md' >%}
{%< 'element.text', as:'h2', variant: 'heading-xl' >%}
Welcome to composable theme components
{%</ 'element.text' >%}
{%< 'element.text', variant: 'rte' >%}
<p>You can compose consistent, high-quality storefronts using well-composed Liquid components</p>
{%</ 'element.text' >%}
{%< 'element.button', text: 'Learn more' >%}
{%</ 'layout.stack' >%}
{%</ 'layout.grid' >%}
{%</ 'layout.section' >%}I'm not at all married to this specific proposal, but at least let's use it to kickstart some creative thinking?
Why don't I just use slots made possible via theme blocks and {% content_for "block" %}?
Short version -- IMO the theme editor shouldn't be a requirement to make slotting + code-reuse possible in Liquid. It should remain a progressive enhancement that selectively exposes points of configurability in the editor.
-
I want to build sections and deal with the theme editor layer later. Why do I need to wrangle a ton of JSON configs to just render something on the page. That's a ton of extra work that I don't need for a first prototype. Let me deal with breaking things into blocks later.
-
I want to have full control when I'm crafting my theme editor experience. I don't want to expose layout.section, layout.grid, and layout.stack as blocks -- I don't think my customers using the editor will care much about those and they'll just add complexity where it's not needed. I'd rather just add a few settings at the section level.
sections/image-with-text.liquid
{%< 'layout.section', padding: section.setting.padding >%}
{%< 'layout.grid', columns_xs: 1, columns_md: 2, gap: 'lg' >%}
{% content_for: 'block', type: 'image' %}
{%< 'layout.stack', gap: 'md' >%}
{% content_for: 'blocks' %}
{%</ 'layout.stack' >%}
{%</ 'layout.grid' >%}
{%</ 'layout.section' >%}blocks/image.liquid
{%< 'element.image', img: block.settings.image >%}blocks/text.liquid
{%< 'element.text', as: block.settings.element, variant: block.settings.variant >%}
{{ block.settings.text }}
{%</ 'element.text' >%}blocks/button.liquid
{%< 'element.button', text: block.settings.text >%}Related issues: