Skip to content

Components and snippets

Reuse markup with snippets, props, children and slots.

A tag whose name starts with a capital letter is a component. Sworen looks for it first among the file’s own named templates, then in your theme’s snippets/ folder. The name is matched loosely: <ProductCard /> finds snippets/product-card.liqx.

snippets/price.liqx
---
const { product } = props;
---
<template>
<span class="price">
{product.price_varies && 'From '}{product.price_min | money_without_trailing_zeros}
<If condition={product.compare_at_price > product.price}>
<s>{product.compare_at_price | money_without_trailing_zeros}</s>
</If>
</span>
</template>

Use it anywhere:

<Price product={product} />
{collection.products.map(item => <Price product={item} />)}

Every attribute you pass becomes a property of props. An attribute without a value is true:

<StarRating rating={product.rating} count={product.reviews_count} size="sm" compact />

Inside snippets/star-rating.liqx: props.rating, props.count, props.size, props.compact.

key is never passed on; use it freely in lists.

Content between the opening and closing tags arrives as props.children. Print it with <slot />:

snippets/card.liqx
<template>
<div class="card">
<header><slot name="title">Untitled</slot></header>
<div class="card__body"><slot /></div>
</div>
</template>
<Card>
<template slot="title"><h3>{product.title}</h3></template>
<p>{product.excerpt}</p>
</Card>

A <template slot="name"> child fills the named slot; the text inside <slot> is shown when nothing was passed.

<template name="Badge">
<span class="badge">{props.text}</span>
</template>
<template>
{product.has_offers && <Badge text="Bundle" />}
</template>

render(name, props) is the function form, useful inside expressions. The second argument becomes the snippet’s props:

{render('price', { product: product })}