SHOPIFY INTEGRATION

Overview

This guide walks you through integrating the ELFBAR Design System into a Shopify Liquid theme. After completing these steps, you will have:

  • Design Tokens — consistent colors, spacing, fonts, and radii across your theme
  • CSS Components — pre-styled UI elements matching the design system
  • Liquid Snippets — reusable template fragments you can render in any section

Final File Structure

your-shopify-theme/
assets/
ds-tokens.css← Design tokens (colors, spacing, fonts)
ds-components.css← Component styles
ds-components.min.js← Interaction logic (optional)
snippets/
ds-button.liquid
ds-card.liquid
ds-badge.liquid
ds-accordion.liquid
...
layout/
theme.liquid← Add stylesheet/script tags here

Prerequisites

Before you begin, make sure you have:

  1. Access to your Shopify theme editor — Go to Shopify Admin → Online Store → Themes → Edit code
  2. The following files (provided by your design system team):
    • ds-tokens.css — Design token variables
    • ds-components.css — Component styles
    • ds-components.min.js — Interaction script (optional, for accordions, tabs, etc.)

Step 1: Add the Design Token File

Design tokens define all the colors, spacing, fonts, and border-radius values used by the design system. They are delivered as CSS variables.

1.1 Create the token file

  1. In the theme editor, navigate to Assets
  2. Click Add a new asset
  3. Choose Create a blank file, name it ds-tokens, select .css
  4. Paste the entire contents of the ds-tokens.css file provided by your design system team
  5. Click Save

1.2 Include in your theme layout

Open layout/theme.liquid and add the following line before the closing </head> tag:

{{ 'ds-tokens.css' | asset_url | stylesheet_tag }}```
 
Place it **after** your theme's main stylesheet so that design system tokens can be accessed by all components.
 
---
 
## Step 2: Add Component Styles
 
Component styles define the visual appearance of each UI element (buttons, cards, badges, etc.).
 
### 2.1 Create the component stylesheet
 
1. In **Assets**, click **Add a new asset**
2. Create a blank `.css` file named `ds-components`
3. Paste the contents of `ds-components.css`
4. Click **Save**
 
### 2.2 Include in your theme layout
 
In `layout/theme.liquid`, add this line right **after** the token stylesheet:
 
```liquid
{{ 'ds-components.css' | asset_url | stylesheet_tag }}```
 
Your `</head>` area should now look like this:
 
```liquid
  {{ 'ds-tokens.css' | asset_url | stylesheet_tag }}
  {{ 'ds-components.css' | asset_url | stylesheet_tag }}
</head>```
 
---
 
## Step 3: Add the Interaction Script (Optional)
 
Some components require JavaScript for interactivity (accordion expand/collapse, tab switching, etc.). If you only need static components like buttons and cards, you can skip this step.
 
### 3.1 Create the script file
 
1. In **Assets**, click **Add a new asset**
2. Create a blank `.js` file named `ds-components.min`
3. Paste the contents of `ds-components.min.js`
4. Click **Save**
 
### 3.2 Include in your theme layout
 
In `layout/theme.liquid`, add this line **before** the closing `</body>` tag:
 
```liquid
{{ 'ds-components.min.js' | asset_url | script_tag }}```
 
---
 
## Step 4: Create Liquid Snippets
 
Snippets are reusable template fragments. Each component has its own snippet file that you create once and use everywhere.
 
### How to create a snippet
 
1. In the theme editor, navigate to **Snippets**
2. Click **Add a new snippet**
3. Name it (e.g., `ds-button`)
4. Paste the code shown below
5. Click **Save**
 
---
 
### Button
 
**Snippet file:** `ds-button.liquid`
 
```liquid
{% comment %}
  Design System Button
  Parameters:
    label     - Button text (required)
    variant   - filled | outlined | text (default: filled)
    size      - sm | md | lg (default: md)
    disabled  - true | false (default: false)
    href      - URL, renders <a> instead of <button>
    type      - button | submit (default: button)
    class     - Additional CSS classes
{% endcomment %}
 
{% assign tag = 'button' %}
{% if href %}{% assign tag = 'a' %}{% endif %}
{% assign v = variant | default: 'filled' %}
{% assign s = size | default: 'md' %}
 
<{{ tag }}
  class="ds-button ds-button--{{ v }} ds-button--{{ s }}{% if disabled %} ds-button--disabled{% endif %}{% if class %} {{ class }}{% endif %}"
  {% if tag == 'button' %}type="{{ type | default: 'button' }}"{% endif %}
  {% if href %}href="{{ href }}"{% endif %}
  {% if disabled %}disabled aria-disabled="true"{% endif %}
>
  {{ label }}
</{{ tag }}>```
 
**Usage examples:**
 
```liquid
{% render 'ds-button', label: 'Add to Cart', variant: 'filled', size: 'lg' %}
 
{% render 'ds-button', label: 'Learn More', variant: 'outlined', href: '/pages/about' %}
 
{% render 'ds-button', label: 'Cancel', variant: 'text' %}```
 
---
 
### Card
 
**Snippet file:** `ds-card.liquid`
 
```liquid
{% comment %}
  Design System Card
  Parameters:
    image_url    - Image source URL
    image_alt    - Image alt text
    title        - Card title
    description  - Card description text
    price        - Price text (e.g., "$12.99")
    href         - Link URL (wraps entire card)
    variant      - standard | horizontal (default: standard)
{% endcomment %}
 
{% assign v = variant | default: 'standard' %}
 
{% if href %}<a href="{{ href }}" class="ds-card-link">{% endif %}
<div class="ds-card ds-card--{{ v }}">
  {% if image_url %}
  <div class="ds-card__image">
    <img src="{{ image_url }}" alt="{{ image_alt | default: title }}" loading="lazy" />
  </div>
  {% endif %}
  <div class="ds-card__content">
    {% if title %}<h3 class="ds-card__title">{{ title }}</h3>{% endif %}
    {% if description %}<p class="ds-card__description">{{ description }}</p>{% endif %}
    {% if price %}
    <div class="ds-card__footer">
      <span class="ds-card__price">{{ price }}</span>
    </div>
    {% endif %}
  </div>
</div>
{% if href %}</a>{% endif %}```
 
**Usage with product data:**
 
```liquid
{% for product in collection.products %}
  {% render 'ds-card',
    image_url: product.featured_image | image_url: width: 600,
    image_alt: product.featured_image.alt,
    title: product.title,
    price: product.price | money,
    href: product.url
  %}
{% endfor %}```
 
---
 
### Badge
 
**Snippet file:** `ds-badge.liquid`
 
```liquid
{% comment %}
  Design System Badge
  Parameters:
    type     - count | dot (default: count)
    count    - Number to display (for count type)
    color    - error | success | warning (default: error)
    position - top-right | top-left (default: top-right)
{% endcomment %}
 
{% assign t = type | default: 'count' %}
{% assign c = color | default: 'error' %}
{% assign p = position | default: 'top-right' %}
 
<span class="ds-badge ds-badge--{{ t }} ds-badge--{{ c }} ds-badge--{{ p }}">
  {% if t == 'count' %}{{ count | default: 0 }}{% endif %}
</span>```
 
---
 
### Accordion (requires JS)
 
**Snippet file:** `ds-accordion.liquid`
 
```liquid
{% comment %}
  Design System Accordion
  Parameters:
    type - single | multiple (default: single)
  Usage: Wrap accordion items in a section block loop
{% endcomment %}
 
{% assign t = type | default: 'single' %}
 
<div class="ds-accordion" data-ds="accordion" data-ds-type="{{ t }}">
  {% for block in section.blocks %}
    {% if block.type == 'accordion_item' %}
    <div class="ds-accordion__item" data-ds-accordion-item {{ block.shopify_attributes }}>
      <button
        class="ds-accordion__trigger"
        data-ds-accordion-trigger
        aria-expanded="false"
        type="button"
      >
        <span>{{ block.settings.title }}</span>
        <svg class="ds-accordion__icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <polyline points="6 9 12 15 18 9"></polyline>
        </svg>
      </button>
      <div class="ds-accordion__content" data-ds-accordion-content hidden>
        <div class="ds-accordion__body">
          {{ block.settings.content }}
        </div>
      </div>
    </div>
    {% endif %}
  {% endfor %}
</div>```
 
**Section schema for accordion:**
 
```json
{
  "name": "FAQ",
  "tag": "section",
  "blocks": [
    {
      "type": "accordion_item",
      "name": "Question",
      "settings": [
        {
          "type": "text",
          "id": "title",
          "label": "Question"
        },
        {
          "type": "richtext",
          "id": "content",
          "label": "Answer"
        }
      ]
    }
  ]
}

This allows merchants to add/remove FAQ items directly from the theme editor.


Skeleton

Snippet file: ds-skeleton.liquid

{% comment %}
  Design System Skeleton
  Parameters:
    type   - text | circle | rect (default: text)
    width  - CSS width value (e.g., "100%", "200px")
    height - CSS height value (e.g., "1rem", "200px")
{% endcomment %}
 
{% assign t = type | default: 'text' %}
 
<div
  class="ds-skeleton ds-skeleton--{{ t }}"
  {% if width or height %}
  style="{% if width %}width: {{ width }};{% endif %}{% if height %}height: {{ height }};{% endif %}"
  {% endif %}
  aria-hidden="true"
></div>```
 
---
 
### Breadcrumb
 
**Snippet file:** `ds-breadcrumb.liquid`
 
```liquid
{% comment %}
  Design System Breadcrumb
  Automatically generates breadcrumbs from the current page context.
{% endcomment %}
 
<nav class="ds-breadcrumb" aria-label="Breadcrumb">
  <ol class="ds-breadcrumb__list">
    <li class="ds-breadcrumb__item">
      <a class="ds-breadcrumb__link" href="/">{{ 'general.breadcrumb.home' | t | default: 'Home' }}</a>
    </li>
    {% if collection %}
    <li class="ds-breadcrumb__item">
      <span class="ds-breadcrumb__separator" aria-hidden="true">/</span>
      <a class="ds-breadcrumb__link" href="{{ collection.url }}">{{ collection.title }}</a>
    </li>
    {% endif %}
    {% if product %}
    <li class="ds-breadcrumb__item">
      <span class="ds-breadcrumb__separator" aria-hidden="true">/</span>
      <span class="ds-breadcrumb__current" aria-current="page">{{ product.title }}</span>
    </li>
    {% endif %}
    {% if page %}
    <li class="ds-breadcrumb__item">
      <span class="ds-breadcrumb__separator" aria-hidden="true">/</span>
      <span class="ds-breadcrumb__current" aria-current="page">{{ page.title }}</span>
    </li>
    {% endif %}
  </ol>
</nav>```
 
---
 
## Step 5: Use Components in Sections & Templates
 
Once your snippets are created, you can use them anywhere in your theme sections and templates.
 
### Example: Product Card Grid Section
 
Create a new section file `sections/ds-product-grid.liquid`:
 
```liquid
<div class="ds-product-grid">
  <div class="ds-product-grid__header">
    {% if section.settings.title != blank %}
      <h2>{{ section.settings.title }}</h2>
    {% endif %}
  </div>
  <div class="ds-product-grid__items">
    {% for product in collections[section.settings.collection].products limit: section.settings.limit %}
      {% render 'ds-card',
        image_url: product.featured_image | image_url: width: 600,
        image_alt: product.featured_image.alt,
        title: product.title,
        price: product.price | money,
        href: product.url
      %}
    {% endfor %}
  </div>
</div>
 
{% schema %}
{
  "name": "Product Grid",
  "settings": [
    {
      "type": "text",
      "id": "title",
      "label": "Section Title",
      "default": "Featured Products"
    },
    {
      "type": "collection",
      "id": "collection",
      "label": "Collection"
    },
    {
      "type": "range",
      "id": "limit",
      "label": "Number of products",
      "min": 2,
      "max": 12,
      "step": 1,
      "default": 4
    }
  ],
  "presets": [
    {
      "name": "Product Grid"
    }
  ]
}
{% endschema %}```
 
### Example: FAQ Section with Accordion
 
Create `sections/ds-faq.liquid`:
 
```liquid
<div class="ds-faq-section">
  {% if section.settings.title != blank %}
    <h2>{{ section.settings.title }}</h2>
  {% endif %}
 
  {% render 'ds-accordion', type: 'single' %}
</div>
 
{% schema %}
{
  "name": "FAQ",
  "settings": [
    {
      "type": "text",
      "id": "title",
      "label": "Section Title",
      "default": "Frequently Asked Questions"
    }
  ],
  "blocks": [
    {
      "type": "accordion_item",
      "name": "Question",
      "settings": [
        {
          "type": "text",
          "id": "title",
          "label": "Question",
          "default": "What is your return policy?"
        },
        {
          "type": "richtext",
          "id": "content",
          "label": "Answer",
          "default": "<p>We offer a 30-day return policy for all unused products.</p>"
        }
      ]
    }
  ],
  "presets": [
    {
      "name": "FAQ",
      "blocks": [
        { "type": "accordion_item" },
        { "type": "accordion_item" },
        { "type": "accordion_item" }
      ]
    }
  ]
}
{% endschema %}```
 
---
 
## Step 6: Brand & Theme Configuration
 
If your store needs to support multiple brands (ELFBAR / Lost Mary) or dark mode, add settings to your theme.
 
### 6.1 Add brand settings
 
Open `config/settings_schema.json` and add this block:
 
```json
{
  "name": "Design System",
  "settings": [
    {
      "type": "select",
      "id": "ds_brand",
      "label": "Brand",
      "options": [
        { "value": "elfbar", "label": "ELFBAR" },
        { "value": "lostmary", "label": "Lost Mary" }
      ],
      "default": "elfbar"
    },
    {
      "type": "checkbox",
      "id": "ds_dark_mode",
      "label": "Enable dark mode",
      "default": false
    }
  ]
}

6.2 Apply brand attributes

In layout/theme.liquid, update the <html> tag:

<html
  lang="{{ request.locale.iso_code }}"
  {% if settings.ds_brand != 'elfbar' %}data-brand="{{ settings.ds_brand }}"{% endif %}
  {% if settings.ds_dark_mode %}data-theme="dark"{% endif %}
>```
 
All design system components will automatically switch to the selected brand's colors and styles.
 
---
 
## Component Reference
 
The table below is automatically generated from the design system source code and shows all available components, their CSS classes, snippet names, and variants.
 
<ComponentCoverageTable />