Using inline partials in Ghost Themes
Inline partials is an underrated feature of Handlebars
Another thing I learned while working on Synaps Media landing page. First let me tell the need:
My designer delivered me some reusable section UIs. When you have repeating components, it's a well known practice to use parametric Handlebars partials, and reuse them in multiple places with different values. Testimonials bubbles in our landing page is a good example.
<figure class="testimonial-wrap">
<div class="testimonial-bubble">
<blockquote>{{quote}}</blockquote>
</div>
<figcaption class="testimonial-profile">
{{#if avatar}}
<img src="{{ img_url avatar size="avatar" }}" srcset="{{ img_url avatar size="avatar2x" }} 2x" alt="{{name}}" width="40" height="40" loading="lazy">
{{/if}}
<div class="testimonial-profile-info">
<strong>{{name}}</strong>
<p>{{handle}}</p>
</div>
</figcaption>
</figure>
And in a place that I want to show a testimonial bubble, I use it like below:
{{> "testimonial"
quote="Some comments"
avatar="https://...."
name="John Doe"
handle="john.doe"
}}This is nice for simple use cases. But I had a section with a slider that I'll highlight some features. And in some cases you might want to pass large HTML content for some targets. To achieve this, in our partials we need to use "inline partials".
<section class="feature-slider-section">
<div class="feature-slider-head">
<div>
<h2 id="feature-slider-heading">{{#> heading}}Change title{{/heading}}</h2>
<p>{{#> description}}Change description{{/description}}</p>
</div>
<div class="feature-slider-nav" aria-hidden="true">
<button type="button" data-dir="-1" aria-label="Previous">
{{> "icons/arrow"}}
</button>
<button type="button" data-dir="1" aria-label="Next">
{{> "icons/arrow"}}
</button>
</div>
</div>
<ul class="feature-slider-track" role="list" tabindex="0" aria-label="Features">
{{#> features}}
<li class="feature-slider-card">
<div class="feature-slider-card-visual"></div>
<h3>Feature title</h3>
<p>Feature description</p>
</li>
{{/features}}
</ul>
</section>{{#> features}} part, create an inline partial with a default value inside. And here how we use it:
{{#> "section-feature-slide"}}
{{#*inline "heading"}}Built for modern publishers{{/inline}}
{{#*inline "description"}}Slide through the features that make Synaps Media the privacy-first analytics platform you actually enjoy using.{{/inline}}
{{#*inline "features"}}
<li class="feature-slider-card">
<div class="feature-slider-card-visual"></div>
<h3>Real-time analytics</h3>
<p>Watch visits land as they happen, with zero cookies and no consent banners.</p>
</li>
<li class="feature-slider-card">
<div class="feature-slider-card-visual"></div>
<h3>Invisible traffic</h3>
<p>Bots, RSS readers and email clients that client-side tracking always misses.</p>
</li>
....
{{/inline}}
{{/ "section-feature-slide"}}
Similar to regular partials, with {{#> "section-feature-slide"}} syntax, we say "I want this partial here". But this time we are able to give partial block contents inside. {{#*inline "features"}} says "put this content inside "features" block in our partial.
That's very handy. Very similar to how "slots" work on web components. Even though syntax is not very intuitive, it does the job.