# Ücretsiz kargo çubuğu: ücretsiz Shopify bölümü

> Canlı sepete ve belirlediğiniz eşiğe göre "Ücretsiz kargoya 23 $ kaldı" mesajı ve ilerleme çubuğu. Sepet çekmecesiyle güncellenir; para birimine göre eşik.

Ücretsiz kargo çubuğu, müşteriye ücretsiz kargoya ne kadar kaldığını "Ücretsiz kargoya 23,00 $ kaldı" gibi bir mesaj ve ilerleme çubuğuyla gösteren ücretsiz bir Shopify bölümüdür. Kalan tutarı sepet toplamından ve belirlediğiniz eşikten hesaplar. Çubuk sayfa açılırken Liquid ile oluşturulur; tema sepete ürün eklediğinde, sepeti değiştirdiğinde ya da boşalttığında sepet yeniden okunur (/cart.js), böylece çubuk sepet çekmecesiyle birlikte güncellenir. Shopify Markets için para birimine göre ayrı eşik girilebilir. Bölüm yalnızca ilerlemeyi gösterir: ücretsiz kargonun kendisini Shopify’da bir kargo ücreti ya da indirim olarak siz tanımlarsınız. Online Store 2.0 temalarında uygulama olmadan çalışır.

- **Kategori:** Dönüşüm ve kampanyalar
- **Kullanıldığı yerler:** Her sayfa, Sepet, Ürün
- **Okuduğu veri:** Sepet (cart nesnesi ve /cart.js)
- **Boyut:** 1 dosyada 17 KB, küçük bir betikle
- **Lisans:** MIT, © 2026 Lintel
- **Sayfa:** https://lintelagency.com/tr/kaynaklar/shopify-bolumleri/ucretsiz-kargo-cubugu
- **Canlı demo:** https://lintelagency.com/resources/shopify-sections/demo/lib-free-shipping-bar.html
- **Eklenme tarihi:** 2026-11-02

## Ne işe yarar

- Ücretsiz kargo kampanyası süresince her sayfanın üstünde ince bir şerit
- Sepet sayfasında ürünlerin üstünde bir kutu
- Ürün sayfalarında satın alma alanının altında, sepete ekle düğmesine yakın bir satır

## Tema düzenleyici ayarları

Bölüm tema düzenleyicide “Lib · Free shipping bar” adıyla görünür. Kimlikler, türler, etiketler ve varsayılan değerler bölümün şemasından gelir. Etiketler tema düzenleyicide göründüğü gibi İngilizcedir.

### Threshold

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `threshold` | `number` | Free shipping from (store currency) | `75` |  |

### Messages

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `message_progress` | `text` | Before the threshold | You're {remaining} away from free shipping |  |
| `message_success` | `text` | Threshold reached | Your order ships free |  |
| `message_empty` | `text` | Empty cart | Free shipping on orders over {threshold} |  |
| `progress_label` | `text` | Progress bar name (screen readers) | Progress to free shipping |  |
| `show_when_empty` | `checkbox` | Show when the cart is empty | `true` |  |
| `hide_when_reached` | `checkbox` | Hide once free shipping is reached | `false` |  |

### Layout

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `style` | `select` | Style | strip | `strip`, `card` |
| `show_icon` | `checkbox` | Show delivery icon | `true` |  |
| `show_progress` | `checkbox` | Show progress bar | `true` |  |
| `section_width` | `select` | Width | page | `page`, `full` |
| `text_alignment` | `select` | Alignment on desktop | center | `left`, `center` |
| `text_alignment_mobile` | `select` | Alignment on mobile | center | `left`, `center` |

### Colors

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `color_bg` | `color` | Background | #F5EFE6 |  |
| `color_bg_gradient` | `color_background` | Background gradient | – |  |
| `color_text` | `color` | Text | #1F1B17 |  |
| `color_accent` | `color` | Progress and icon | #4F6B3A |  |
| `color_track` | `color` | Progress track | #E2D9CC |  |
| `color_card` | `color` | Box background | #FFFFFF |  |

### Spacing and visibility

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `padding_top` | `range` | Top padding on desktop | `16` | 0–120 px, step 4 |
| `padding_bottom` | `range` | Bottom padding on desktop | `16` | 0–120 px, step 4 |
| `padding_top_mobile` | `range` | Top padding on mobile | `12` | 0–120 px, step 4 |
| `padding_bottom_mobile` | `range` | Bottom padding on mobile | `12` | 0–120 px, step 4 |
| `show_on` | `select` | Show on | all | `all`, `desktop`, `mobile` |
| `anchor_id` | `text` | Anchor ID | – |  |

### Motion

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `animate` | `checkbox` | Animate the progress bar | `true` |  |

## Bloklar

Toplamda en fazla 20 blok.

### Currency threshold (`currency`)

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `currency` | `text` | Currency code | EUR |  |
| `amount` | `number` | Free shipping from | `70` |  |

## Kurulum

### Shopify yönetim panelinde

1. Canlı temanızda değil, bir kopyasında çalışın: Shopify yönetim panelinde **Online Mağaza > Temalar** sayfasına gidin, mevcut temanızın **…** menüsünü açın ve **Kopya oluştur**’u seçin.
2. Kopyada **…** menüsünü açın ve **Kodu düzenle**’yi seçin.
3. `sections` klasörüne `lib-free-shipping-bar.liquid` adında yeni bir dosya ekleyin, aşağıdaki kaynak koddan `sections/lib-free-shipping-bar.liquid` içeriğini yapıştırıp kaydedin.
4. Kopyada **Özelleştir**’i açın, **Bölüm ekle**’yi seçin ve **Lib · Free shipping bar** bölümünü ekleyin. Örnek içeriği kendi içeriğinizle değiştirin, renkleri ayarlayın.
5. Kopyayı önizleyin, her şey doğru göründüğünde yayınlayın.

### Shopify CLI ile

Yerel tema klasörünüzde dosyaları indirin ve yalnızca bunları yayında olmayan bir temaya gönderin (temanın kimliğini `shopify theme list` gösterir):

```sh
curl -fsSL -o sections/lib-free-shipping-bar.liquid https://lintelagency.com/resources/shopify-sections/files/lib-free-shipping-bar.liquid
shopify theme push --theme <unpublished-theme-id> --only sections/lib-free-shipping-bar.liquid
```

Canlı temaya asla göndermeyin: her zaman yayında olmayan bir temanın kimliğini verin, `--live` ya da `--allow-live` kullanmayın. Ardından bölümü yukarıdaki gibi tema düzenleyicide ekleyin.

## Dosyalar

- [sections/lib-free-shipping-bar.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-free-shipping-bar.liquid): `sections/` klasörüne

## Sık sorulan sorular

### Bu bölüm müşterilere ücretsiz kargo sağlıyor mu?

Hayır. Yalnızca yazdığınız eşiğe doğru ilerlemeyi gösterir. Ücretsiz kargonun kendisini Shopify’da tanımlayın: Ayarlar > Kargo ve teslimat altında minimum sipariş tutarı koşullu ücretsiz bir kargo ücreti ya da İndirimler altında bir ücretsiz kargo indirimi oluşturun; ikisinde de bölümdeki eşikle aynı tutarı kullanın.

### Hangi sepet toplamını kullanıyor?

Shopify’ın bildirdiği sepet toplamını (total_price): sepet indirimlerinden sonra, kargo ve vergilerden önce. Kargo ücreti koşulunuz farklı bir toplam kullanıyorsa eşiği, ikisi aynı sonucu verecek şekilde ayarlayın.

### Ürünler sepet çekmecesinden eklenince güncelleniyor mu?

Evet. Betik, Shopify’ın sepet adreslerine (add, change, update, clear) giden isteklerin tamamlanmasını ve birçok temanın gönderdiği cart:updated olaylarını izler; ardından /cart.js’i yeniden okuyup mesajı ve çubuğu günceller.

### Başka para birimlerinde nasıl çalışıyor?

Para birimi kodunu ve tam tutarı girdiğiniz bir Para birimi eşiği bloğu ekleyin, örneğin EUR 70. Blok eklemezseniz mağaza eşiği Shopify’ın güncel kuruyla çevrilir; bu da küsuratlı bir tutara yol açabilir.

### Ücretsiz kargoya ulaşılınca ya da sepet boşken gizleyebilir miyim?

Evet, ikisi için de bir ayar var. Boş sepet, ilerleme ve başarı mesajları {remaining} ve {threshold} yer tutucularıyla değiştirip çevirebileceğiniz metinlerdir.

## Kaynak kod

### sections/lib-free-shipping-bar.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{%- comment -%}
  Free shipping bar: "You're $23.00 away from free shipping" with a progress bar, worked out from
  the cart total and the threshold you type. Liquid renders it from the cart on page load; a small
  script reads /cart.js again whenever the theme changes the cart (add, change, update, clear), so
  the message follows a cart drawer. Thresholds can be set per currency for Shopify Markets;
  otherwise the store's threshold is converted at Shopify's rate. The section only displays: the
  free shipping itself must be set up in Shopify (shipping rates or a free shipping discount).
  Depends on: nothing
{%- endcomment -%}

{%- liquid
  assign s = section.settings
  assign currency = cart.currency.iso_code | default: shop.currency
  assign threshold = s.threshold | times: 100 | round
  assign exact = false
  if currency == shop.currency
    assign exact = true
  endif
  for block in section.blocks
    assign code = block.settings.currency | strip | upcase
    if code == currency and block.settings.amount > 0
      assign threshold = block.settings.amount | times: 100 | round
      assign exact = true
    endif
  endfor

  assign total = cart.total_price | default: 0
  assign remaining = threshold | minus: total
  assign state = 'progress'
  if cart.item_count == 0
    assign state = 'empty'
  elsif remaining <= 0
    assign state = 'done'
    assign remaining = 0
  endif
  assign percent = 0
  if threshold > 0
    assign percent = total | times: 100 | divided_by: threshold
  endif
  if percent > 100
    assign percent = 100
  endif

  assign hide = false
  if state == 'empty' and s.show_when_empty == false
    assign hide = true
  endif
  if state == 'done' and s.hide_when_reached
    assign hide = true
  endif
  # Another currency without its own threshold: the script converts at Shopify's rate first.
  if exact == false
    assign hide = true
  endif
  if request.design_mode
    assign hide = false
  endif

  assign message = s.message_progress
  if state == 'empty'
    assign message = s.message_empty
  elsif state == 'done'
    assign message = s.message_success
  endif
  assign remaining_money = remaining | money
  assign threshold_money = threshold | money
  assign remaining_html = '<strong>' | append: remaining_money | append: '</strong>'
  assign threshold_html = '<strong>' | append: threshold_money | append: '</strong>'
  assign message = message | escape | replace: '{remaining}', remaining_html | replace: '{threshold}', threshold_html
-%}

<lib-free-shipping-bar
  class="lib-ship-bar lib-ship-bar--{{ s.section_width }}"
  {% if s.anchor_id != blank %}
    id="{{ s.anchor_id | handleize }}"
  {% endif %}
  data-show="{{ s.show_on }}"
  data-style="{{ s.style }}"
  data-state="{{ state }}"
  data-threshold="{{ threshold }}"
  data-currency="{{ currency }}"
  data-locale="{{ request.locale.iso_code }}"
  data-root="{{ routes.root_url }}"
  {% unless exact %}
    data-convert
  {% endunless %}
  {% if s.show_when_empty == false %}
    data-hide-empty
  {% endif %}
  {% if s.hide_when_reached %}
    data-hide-done
  {% endif %}
  {% if s.animate %}
    data-animate
  {% endif %}
  {% if hide %}
    hidden
  {% endif %}
  style="
    --lib-bg: {{ s.color_bg }};
    {% if s.color_bg_gradient != blank %}--lib-bg-image: {{ s.color_bg_gradient }};{% endif %}
    --lib-text: {{ s.color_text }};
    --lib-accent: {{ s.color_accent }};
    --lib-track: {{ s.color_track }};
    --lib-card: {{ s.color_card }};
    --lib-pt: {{ s.padding_top }}px;
    --lib-pb: {{ s.padding_bottom }}px;
    --lib-pt-m: {{ s.padding_top_mobile }}px;
    --lib-pb-m: {{ s.padding_bottom_mobile }}px;
  "
>
  <div class="lib-ship-bar__inner" data-align="{{ s.text_alignment }}" data-align-m="{{ s.text_alignment_mobile }}">
    <div class="lib-ship-bar__row">
      {%- if s.show_icon -%}
        <svg class="lib-ship-bar__icon" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
          <path d="M3 6h11v10H3zM14 9h4l3 3v4h-7"/><circle cx="7" cy="17.5" r="1.8"/><circle cx="17" cy="17.5" r="1.8"/>
        </svg>
      {%- endif -%}
      <p class="lib-ship-bar__message" aria-live="polite" data-message>{{ message }}</p>
    </div>
    {%- if s.show_progress -%}
      <div
        class="lib-ship-bar__track"
        role="progressbar"
        aria-label="{{ s.progress_label | escape }}"
        aria-valuemin="0"
        aria-valuemax="100"
        aria-valuenow="{{ percent }}"
        data-track
        {% if state == 'empty' %}
          hidden
        {% endif %}
      >
        <span class="lib-ship-bar__fill" style="width: {{ percent }}%;" data-fill></span>
      </div>
    {%- endif -%}
  </div>
  <template data-templates>
    <span data-key="empty">{{ s.message_empty | escape }}</span>
    <span data-key="progress">{{ s.message_progress | escape }}</span>
    <span data-key="done">{{ s.message_success | escape }}</span>
  </template>
</lib-free-shipping-bar>

{% stylesheet %}
  .lib-ship-bar {
    display: block;
    background-color: var(--lib-bg);
    background-image: var(--lib-bg-image, none);
    color: var(--lib-text);
    padding: var(--lib-pt) 1rem var(--lib-pb);
  }
  .lib-ship-bar[hidden] { display: none; }
  .lib-ship-bar__inner { max-width: 1200px; margin: 0 auto; }
  .lib-ship-bar--full .lib-ship-bar__inner { max-width: none; }
  .lib-ship-bar[data-style='card'] .lib-ship-bar__inner {
    max-width: 36rem;
    padding: clamp(1rem, 2.5vw, 1.5rem);
    border-radius: 14px;
    background: var(--lib-card);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--lib-text) 10%, transparent);
  }
  @media (max-width: 749px) {
    .lib-ship-bar { padding-top: var(--lib-pt-m); padding-bottom: var(--lib-pb-m); }
    .lib-ship-bar[data-show='desktop'] { display: none; }
  }
  @media (min-width: 750px) {
    .lib-ship-bar[data-show='mobile'] { display: none; }
  }

  .lib-ship-bar__row { display: flex; align-items: center; gap: 0.625rem; }
  .lib-ship-bar__icon { flex: none; width: 1.375rem; height: 1.375rem; color: var(--lib-accent); }
  .lib-ship-bar__message { margin: 0; font-size: 0.9375rem; line-height: 1.45; }
  .lib-ship-bar__message strong { font-weight: 700; }

  .lib-ship-bar__track {
    position: relative;
    height: 0.5rem;
    margin-top: 0.625rem;
    overflow: hidden;
    border-radius: 999px;
    background: var(--lib-track);
  }
  .lib-ship-bar__track[hidden] { display: none; }
  .lib-ship-bar__fill {
    position: absolute;
    inset: 0 auto 0 0;
    max-width: 100%;
    border-radius: inherit;
    background: var(--lib-accent);
  }
  @media (prefers-reduced-motion: no-preference) {
    .lib-ship-bar[data-animate] .lib-ship-bar__fill { transition: width 0.6s cubic-bezier(0.2, 0.7, 0.2, 1); }
  }

  .lib-ship-bar__inner[data-align='center'] .lib-ship-bar__row { justify-content: center; text-align: center; }
  .lib-ship-bar__inner[data-align='center'] .lib-ship-bar__track { max-width: 28rem; margin-inline: auto; }
  @media (max-width: 749px) {
    .lib-ship-bar__inner[data-align-m='left'] .lib-ship-bar__row { justify-content: flex-start; text-align: left; }
    .lib-ship-bar__inner[data-align-m='left'] .lib-ship-bar__track { max-width: none; }
    .lib-ship-bar__inner[data-align-m='center'] .lib-ship-bar__row { justify-content: center; text-align: center; }
  }
{% endstylesheet %}

{% javascript %}
  (() => {
    if (customElements.get('lib-free-shipping-bar')) return;
    // Cart Ajax API endpoints that change the cart; a finished request to one means "read the cart again".
    const CART_CHANGES = /\/cart\/(add|change|update|clear)(\.js)?(\?|$)/;
    const REFRESH_DELAY_MS = 150;
    // Events some themes and apps dispatch after a cart change.
    const CART_EVENTS = ['cart:updated', 'cart:refresh', 'cart:change'];

    class LibFreeShippingBar extends HTMLElement {
      connectedCallback() {
        this.messages = Object.fromEntries(
          [...this.querySelector('[data-templates]').content.querySelectorAll('[data-key]')].map((el) => [el.dataset.key, el.textContent]),
        );
        this.base = Number(this.dataset.threshold) || 0;
        this.refresh = this.refresh.bind(this);
        this.scheduled = null;
        const schedule = () => {
          clearTimeout(this.scheduled);
          this.scheduled = setTimeout(this.refresh, REFRESH_DELAY_MS);
        };
        if ('PerformanceObserver' in window) {
          this.observer = new PerformanceObserver((list) => {
            if (list.getEntries().some((e) => CART_CHANGES.test(new URL(e.name, location.href).pathname))) schedule();
          });
          try {
            this.observer.observe({type: 'resource', buffered: false});
          } catch (error) {
            // Old browsers without resource timing: the events below still work.
            this.observer = null;
          }
        }
        this.onEvent = schedule;
        CART_EVENTS.forEach((name) => document.addEventListener(name, this.onEvent));
        this.onShow = (event) => event.persisted && schedule();
        window.addEventListener('pageshow', this.onShow);
        if (this.hasAttribute('data-convert')) this.refresh();
      }

      disconnectedCallback() {
        this.observer?.disconnect();
        CART_EVENTS.forEach((name) => document.removeEventListener(name, this.onEvent));
        window.removeEventListener('pageshow', this.onShow);
      }

      threshold() {
        if (!this.hasAttribute('data-convert')) return this.base;
        // Shopify Markets: convert the store's threshold at the storefront's own rate.
        const rate = Number(window.Shopify?.currency?.rate) || 1;
        return Math.round(this.base * rate);
      }

      format(cents, currency) {
        try {
          return new Intl.NumberFormat(this.dataset.locale || undefined, {style: 'currency', currency}).format(cents / 100);
        } catch (error) {
          // Unknown locale or currency code: a plain number still reads correctly.
          return (cents / 100).toFixed(2);
        }
      }

      async refresh() {
        let cart;
        try {
          const response = await fetch(`${this.dataset.root || '/'}cart.js`, {headers: {Accept: 'application/json'}});
          if (!response.ok) throw new Error(`cart.js answered ${response.status}`);
          cart = await response.json();
        } catch (error) {
          // Keep the last message rather than show a wrong one.
          console.warn('Free shipping bar: the cart could not be read.', error);
          return;
        }
        const currency = cart.currency || this.dataset.currency;
        const threshold = this.threshold();
        const total = Number(cart.total_price) || 0;
        const remaining = Math.max(0, threshold - total);
        const state = cart.item_count === 0 ? 'empty' : remaining === 0 ? 'done' : 'progress';
        const percent = threshold > 0 ? Math.min(100, Math.floor((total / threshold) * 100)) : 0;
        this.render(state, percent, {remaining: this.format(remaining, currency), threshold: this.format(threshold, currency)});
      }

      render(state, percent, values) {
        this.dataset.state = state;
        const message = this.querySelector('[data-message]');
        const parts = (this.messages[state] || '').split(/(\{remaining\}|\{threshold\})/);
        message.replaceChildren(
          ...parts.map((part) => {
            const key = part.slice(1, -1);
            if (!(key in values) || part[0] !== '{') return part;
            const strong = document.createElement('strong');
            strong.textContent = values[key];
            return strong;
          }),
        );
        const track = this.querySelector('[data-track]');
        if (track) {
          track.hidden = state === 'empty';
          track.setAttribute('aria-valuenow', String(percent));
          this.querySelector('[data-fill]').style.width = `${percent}%`;
        }
        this.hidden =
          (state === 'empty' && this.hasAttribute('data-hide-empty')) || (state === 'done' && this.hasAttribute('data-hide-done'));
      }
    }
    customElements.define('lib-free-shipping-bar', LibFreeShippingBar);
  })();
{% endjavascript %}

{% schema %}
{
  "name": "Lib · Free shipping bar",
  "tag": "section",
  "class": "lib-section",
  "max_blocks": 20,
  "settings": [
    { "type": "paragraph", "content": "This bar only shows progress. Set up the free shipping itself in Settings > Shipping and delivery (a free rate with a minimum order price) or as a free shipping discount, with the same amount." },
    { "type": "header", "content": "Threshold" },
    { "type": "number", "id": "threshold", "label": "Free shipping from (store currency)", "info": "Cart total after discounts, before shipping and taxes. Add a Currency threshold block for an exact amount in another currency.", "default": 75 },

    { "type": "header", "content": "Messages" },
    { "type": "text", "id": "message_progress", "label": "Before the threshold", "info": "{remaining} is the amount left, {threshold} the threshold.", "default": "You're {remaining} away from free shipping" },
    { "type": "text", "id": "message_success", "label": "Threshold reached", "default": "Your order ships free" },
    { "type": "text", "id": "message_empty", "label": "Empty cart", "info": "{threshold} is the threshold.", "default": "Free shipping on orders over {threshold}" },
    { "type": "text", "id": "progress_label", "label": "Progress bar name (screen readers)", "default": "Progress to free shipping" },
    { "type": "checkbox", "id": "show_when_empty", "label": "Show when the cart is empty", "default": true },
    { "type": "checkbox", "id": "hide_when_reached", "label": "Hide once free shipping is reached", "default": false },

    { "type": "header", "content": "Layout" },
    {
      "type": "select",
      "id": "style",
      "label": "Style",
      "info": "Strip suits the top of a page; box suits the cart page.",
      "options": [
        { "value": "strip", "label": "Strip" },
        { "value": "card", "label": "Box" }
      ],
      "default": "strip"
    },
    { "type": "checkbox", "id": "show_icon", "label": "Show delivery icon", "default": true },
    { "type": "checkbox", "id": "show_progress", "label": "Show progress bar", "default": true },
    {
      "type": "select",
      "id": "section_width",
      "label": "Width",
      "options": [
        { "value": "page", "label": "Page width" },
        { "value": "full", "label": "Full width" }
      ],
      "default": "page"
    },
    {
      "type": "select",
      "id": "text_alignment",
      "label": "Alignment on desktop",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" }
      ],
      "default": "center"
    },
    {
      "type": "select",
      "id": "text_alignment_mobile",
      "label": "Alignment on mobile",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" }
      ],
      "default": "center"
    },

    { "type": "header", "content": "Colors" },
    { "type": "color", "id": "color_bg", "label": "Background", "default": "#F5EFE6" },
    { "type": "color_background", "id": "color_bg_gradient", "label": "Background gradient", "info": "Optional. Covers the background color." },
    { "type": "color", "id": "color_text", "label": "Text", "default": "#1F1B17" },
    { "type": "color", "id": "color_accent", "label": "Progress and icon", "default": "#4F6B3A" },
    { "type": "color", "id": "color_track", "label": "Progress track", "default": "#E2D9CC" },
    { "type": "color", "id": "color_card", "label": "Box background", "default": "#FFFFFF" },

    { "type": "header", "content": "Spacing and visibility" },
    { "type": "range", "id": "padding_top", "label": "Top padding on desktop", "min": 0, "max": 120, "step": 4, "unit": "px", "default": 16 },
    { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 120, "step": 4, "unit": "px", "default": 16 },
    { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 120, "step": 4, "unit": "px", "default": 12 },
    { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 120, "step": 4, "unit": "px", "default": 12 },
    {
      "type": "select",
      "id": "show_on",
      "label": "Show on",
      "options": [
        { "value": "all", "label": "All devices" },
        { "value": "desktop", "label": "Desktop only" },
        { "value": "mobile", "label": "Mobile only" }
      ],
      "default": "all"
    },
    { "type": "text", "id": "anchor_id", "label": "Anchor ID", "info": "Optional. Link to this section with #your-id." },

    { "type": "header", "content": "Motion" },
    { "type": "checkbox", "id": "animate", "label": "Animate the progress bar", "info": "Never when reduced motion is on.", "default": true }
  ],
  "blocks": [
    {
      "type": "currency",
      "name": "Currency threshold",
      "settings": [
        { "type": "paragraph", "content": "An exact threshold for shoppers who pay in another currency (Shopify Markets). Without one, the store's threshold is converted at Shopify's rate." },
        { "type": "text", "id": "currency", "label": "Currency code", "info": "Three letters, for example EUR or GBP.", "default": "EUR" },
        { "type": "number", "id": "amount", "label": "Free shipping from", "default": 70 }
      ]
    }
  ],
  "presets": [{ "name": "Lib · Free shipping bar" }]
}
{% endschema %}
```

## Lisans

MIT Lisansı, © 2026 Lintel. Kendi mağazanızda ya da müşteri işlerinde ücretsiz kullanabilir, değiştirebilir ve yayınlayabilirsiniz; her dosyanın başındaki lisans satırını koruyun.
