# Müşteri fotoğraf galerisi: ücretsiz Shopify bölümü

> Yüklediğiniz müşteri fotoğraflarıyla Instagram tarzı bir ızgara; her fotoğraf, içindeki ürüne adı ve fiyatıyla bağlanır. Instagram API’si de uygulama da yok.

Müşteri fotoğraf galerisi, müşteri fotoğraflarını Instagram tarzı bir ızgarada sergileyen ücretsiz bir Shopify bölümüdür. Müşterilerin sizinle paylaştığı fotoğrafları kendiniz yüklersiniz; her fotoğraf, adı ve fiyatı mağazanızdan gelen ürüne bağlanabilir ve isteğe bağlı olarak fotoğraf sahibini belirten bir not taşıyabilir. Instagram’dan ya da başka bir hizmetten hiçbir şey çekilmez; yenilenmesi gereken bir API anahtarı, üçüncü taraf betiği ya da izleme yoktur. Fotoğrafları, diğer tema görselleri gibi Shopify duyarlı boyutlarda sunar. Alttaki bir düğme, ziyaretçileri hashtag sayfanıza ya da bir gönderim formuna yönlendirebilir. Online Store 2.0 temaları için düz Liquid ve CSS’tir.

- **Kategori:** Sosyal kanıt ve güven
- **Kullanıldığı yerler:** Ana sayfa, Ürün, Hakkımızda
- **Okuduğu veri:** Yüklenen fotoğraflar, ürünler
- **Boyut:** 3 dosyada 21 KB, JavaScript yok
- **Lisans:** MIT, © 2026 Lintel
- **Sayfa:** https://lintelagency.com/tr/kaynaklar/shopify-bolumleri/musteri-fotograf-galerisi
- **Canlı demo:** https://lintelagency.com/resources/shopify-sections/demo/lib-ugc-gallery.html
- **Eklenme tarihi:** 2026-11-02

## Ne işe yarar

- Ana sayfada, fotoğraflardaki ürünlere bağlantı veren bir "Evlerinizden" ızgarası
- Ürün sayfasında, ürünü gerçek kullanımda gösteren müşteri fotoğrafları
- Müşterileri fotoğraflarını paylaşmaya davet eden, düğmeli bir topluluk sayfası

## Tema düzenleyici ayarları

Bölüm tema düzenleyicide “Lib · UGC gallery” 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.

### Content

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `heading` | `inline_richtext` | Heading | In your homes |  |
| `heading_tag` | `select` | Heading tag | h2 | `h1`, `h2`, `h3`, `p` |
| `heading_size` | `select` | Heading size | medium | `small`, `medium`, `large` |
| `text` | `richtext` | Intro text | – |  |
| `button_label` | `text` | Button text | – |  |
| `button_url` | `url` | Button link | – |  |
| `button_style` | `select` | Button style | outline | `primary`, `outline`, `text` |
| `button_new_tab` | `checkbox` | Open button link in a new tab | `false` |  |

### Product links

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `show_product` | `checkbox` | Show the product in each photo | `true` |  |
| `product_prefix` | `text` | Text before the product name | Shop |  |
| `show_price` | `checkbox` | Show price | `true` |  |

### Layout

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `columns` | `range` | Columns on desktop | `3` | 2–6, step 1 |
| `columns_mobile` | `range` | Columns on mobile | `2` | 1–3, step 1 |
| `image_ratio` | `select` | Photo shape | square | `square`, `portrait` |
| `gap` | `range` | Space between photos | `8` | 0–24 px, step 2 |
| `radius` | `range` | Corner radius | `10` | 0–24 px, step 2 |
| `section_width` | `select` | Width | page | `page`, `full` |
| `text_alignment` | `select` | Heading alignment on desktop | center | `left`, `center` |
| `text_alignment_mobile` | `select` | Heading alignment on mobile | left | `left`, `center` |

### Colors

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `color_bg` | `color` | Background | #FFFFFF |  |
| `color_bg_gradient` | `color_background` | Background gradient | – |  |
| `color_text` | `color` | Text | #1F1B17 |  |
| `color_accent` | `color` | Accent (button, focus) | #7A5A3A |  |
| `color_accent_text` | `color` | Text on accent | #FFFFFF |  |
| `color_chip` | `color` | Product label background | #FFFFFF |  |
| `color_chip_text` | `color` | Product label text | #1F1B17 |  |

### Spacing and visibility

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `padding_top` | `range` | Top padding on desktop | `64` | 0–200 px, step 4 |
| `padding_bottom` | `range` | Bottom padding on desktop | `64` | 0–200 px, step 4 |
| `padding_top_mobile` | `range` | Top padding on mobile | `40` | 0–160 px, step 4 |
| `padding_bottom_mobile` | `range` | Bottom padding on mobile | `40` | 0–160 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` | Zoom photos slightly on hover | `true` |  |

## Bloklar

Toplamda en fazla 24 blok.

### Photo (`photo`)

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `image` | `image_picker` | Photo | – |  |
| `image_mobile` | `image_picker` | Mobile photo | – |  |
| `credit` | `text` | Credit | – |  |
| `product` | `product` | Product in the photo | – |  |

## 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-ugc-gallery.liquid` adında yeni bir dosya ekleyin, aşağıdaki kaynak koddan `sections/lib-ugc-gallery.liquid` içeriğini yapıştırıp kaydedin.
4. `lib-image.liquid` ve `lib-button.liquid` dosyalarını da aynı şekilde `snippets` klasörüne ekleyin. Başka bir Lib bölümünden gelen aynı adlı bir snippet zaten varsa aynı dosyadır; tek kopya yeterli.
5. Kopyada **Özelleştir**’i açın, **Bölüm ekle**’yi seçin ve **Lib · UGC gallery** bölümünü ekleyin. Örnek içeriği kendi içeriğinizle değiştirin, renkleri ayarlayın.
6. 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-ugc-gallery.liquid https://lintelagency.com/resources/shopify-sections/files/lib-ugc-gallery.liquid
curl -fsSL -o snippets/lib-image.liquid https://lintelagency.com/resources/shopify-sections/files/lib-image.liquid
curl -fsSL -o snippets/lib-button.liquid https://lintelagency.com/resources/shopify-sections/files/lib-button.liquid
shopify theme push --theme <unpublished-theme-id> --only sections/lib-ugc-gallery.liquid --only snippets/lib-image.liquid --only snippets/lib-button.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-ugc-gallery.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-ugc-gallery.liquid): `sections/` klasörüne
- [snippets/lib-image.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-image.liquid): `snippets/` klasörüne
- [snippets/lib-button.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-button.liquid): `snippets/` klasörüne

## Sık sorulan sorular

### Instagram’a bağlanıyor mu?

Hayır. Fotoğrafları bölüme kendiniz yüklersiniz. Böylece Instagram API’siyle, süresi dolan anahtarlarla ve sayfayı yavaşlatan üçüncü taraf yerleştirmeleriyle uğraşmazsınız; hangi fotoğrafların görüneceğine de tamamen siz karar verirsiniz.

### Müşterilerin fotoğraflarını kullanabilir miyim?

Yalnızca izin alarak. Bir fotoğrafı yayınlamadan önce sahibine sorun, adını onun kabul ettiği şekilde belirtin ve onayın kaydını saklayın. Demodaki fotoğraflar gerçek müşterilere ait değil, üretilmiş görsellerdir.

### Ürün bağlantıları nasıl çalışıyor?

Fotoğrafın bloğunda bir ürün seçin: ürünün adını ve fiyatını (mağazanızdan geldiği için her zaman günceldir) gösteren bir etiket, ürün sayfasına bağlanır. Mobilde yer kazanmak için etiket yalnızca ürün adını gösterir.

### Kaç fotoğraf ekleyebilirim?

En çok 24; masaüstünde 2–6, mobilde 1–3 sütun halinde, kare ya da dikey. Ekran okuyucuların fotoğrafı tarif edebilmesi için her fotoğrafın alternatif metnini görselin ayrıntılarına girin.

## Kaynak kod

### sections/lib-ugc-gallery.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{%- comment -%}
  UGC gallery: customer photos in an Instagram-style grid, uploaded by the merchant, each with an
  optional credit and a link to the product in it (name and price from the store). No Instagram
  API, no third-party embed, no tracking: photos are served by Shopify like any theme image. Ask
  customers before you post their photos. Pure Liquid and CSS; no JavaScript.
  Depends on: snippets/lib-image.liquid, snippets/lib-button.liquid
{%- endcomment -%}

{%- liquid
  assign s = section.settings
  assign heading_tag = s.heading_tag | default: 'h2'
  assign cols = s.columns | plus: 0
  assign img_vw = 100 | divided_by: cols
  assign cols_m = s.columns_mobile | plus: 0
  assign img_vw_m = 100 | divided_by: cols_m
  assign img_sizes = '(min-width: 750px) ' | append: img_vw | append: 'vw, ' | append: img_vw_m | append: 'vw'
-%}

<div
  class="lib-ugc lib-ugc--{{ s.section_width }}"
  {% if s.anchor_id != blank %}
    id="{{ s.anchor_id | handleize }}"
  {% endif %}
  data-show="{{ s.show_on }}"
  data-ratio="{{ s.image_ratio }}"
  {% if s.animate %}
    data-animate
  {% 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-accent-text: {{ s.color_accent_text }};
    --lib-chip: {{ s.color_chip }};
    --lib-chip-text: {{ s.color_chip_text }};
    --lib-cols: {{ cols }};
    --lib-cols-m: {{ cols_m }};
    --lib-gap: {{ s.gap }}px;
    --lib-radius: {{ s.radius }}px;
    --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-ugc__inner">
    {%- if s.heading != blank or s.text != blank -%}
      <header class="lib-ugc__header" data-align="{{ s.text_alignment }}" data-align-m="{{ s.text_alignment_mobile }}">
        {%- if s.heading != blank -%}
          <{{ heading_tag }} class="lib-ugc__heading lib-ugc__heading--{{ s.heading_size }}">
            {{- s.heading -}}
          </{{ heading_tag }}>
        {%- endif -%}
        {%- if s.text != blank -%}
          <div class="lib-ugc__text">{{ s.text }}</div>
        {%- endif -%}
      </header>
    {%- endif -%}

    {%- if section.blocks.size > 0 -%}
      <ul class="lib-ugc__grid" role="list">
        {%- for block in section.blocks -%}
          {%- assign b = block.settings -%}
          {%- assign p = b.product -%}
          <li class="lib-ugc__item" {{ block.shopify_attributes }}>
            <figure class="lib-ugc__figure">
              <div class="lib-ugc__media">
                {%- render 'lib-image', image: b.image, image_mobile: b.image_mobile, class: 'lib-ugc__img', sizes: img_sizes, placeholder: 'lifestyle-2' -%}
              </div>
              {%- if b.credit != blank or p != blank -%}
                <figcaption class="lib-ugc__caption">
                  {%- if b.credit != blank -%}
                    <span class="lib-ugc__credit">{{ b.credit | escape }}</span>
                  {%- endif -%}
                  {%- if p != blank and s.show_product -%}
                    <a class="lib-ugc__chip" href="{{ p.url }}">
                      {%- if s.product_prefix != blank -%}<span class="lib-ugc__prefix">{{ s.product_prefix | escape }}</span>{%- endif -%}
                      <span class="lib-ugc__product">{{ p.title | escape }}</span>
                      {%- if s.show_price -%}<span class="lib-ugc__price">{{ p.price | money }}</span>{%- endif -%}
                    </a>
                  {%- endif -%}
                </figcaption>
              {%- endif -%}
            </figure>
          </li>
        {%- endfor -%}
      </ul>
    {%- endif -%}

    {%- if s.button_label != blank -%}
      <div class="lib-ugc__more">
        {%- render 'lib-button', label: s.button_label, url: s.button_url, style: s.button_style, new_tab: s.button_new_tab -%}
      </div>
    {%- endif -%}
  </div>
</div>

{% stylesheet %}
  .lib-ugc {
    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-ugc__inner { max-width: 1200px; margin: 0 auto; }
  .lib-ugc--full { padding-inline: var(--lib-gap); }
  .lib-ugc--full .lib-ugc__inner { max-width: none; }
  @media (max-width: 749px) {
    .lib-ugc { padding-top: var(--lib-pt-m); padding-bottom: var(--lib-pb-m); }
    .lib-ugc[data-show='desktop'] { display: none; }
  }
  @media (min-width: 750px) {
    .lib-ugc[data-show='mobile'] { display: none; }
  }

  .lib-ugc__header { max-width: 42rem; margin-bottom: clamp(1.25rem, 3vw, 2rem); }
  .lib-ugc__heading {
    margin: 0;
    font-size: clamp(1.75rem, 3vw, 2.5rem);
    line-height: 1.15;
    letter-spacing: -0.02em;
    text-wrap: balance;
  }
  .lib-ugc__heading--small { font-size: clamp(1.25rem, 1.8vw, 1.5rem); }
  .lib-ugc__heading--large { font-size: clamp(2rem, 4vw, 3.25rem); }
  .lib-ugc__text { margin-top: 0.6rem; font-size: 1rem; line-height: 1.6; opacity: 0.85; }
  .lib-ugc__text > :first-child { margin-top: 0; }
  .lib-ugc__text > :last-child { margin-bottom: 0; }
  .lib-ugc__header[data-align='center'] { margin-inline: auto; text-align: center; }
  @media (max-width: 749px) {
    .lib-ugc__header[data-align-m='left'] { margin-inline: 0; text-align: left; }
    .lib-ugc__header[data-align-m='center'] { margin-inline: auto; text-align: center; }
  }

  .lib-ugc__grid {
    display: grid;
    grid-template-columns: repeat(var(--lib-cols), minmax(0, 1fr));
    gap: var(--lib-gap);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  @media (max-width: 749px) {
    .lib-ugc__grid { grid-template-columns: repeat(var(--lib-cols-m), minmax(0, 1fr)); }
  }
  .lib-ugc__item { min-width: 0; }
  .lib-ugc__figure { position: relative; margin: 0; overflow: hidden; border-radius: var(--lib-radius); }
  .lib-ugc__media { aspect-ratio: 1; background: color-mix(in srgb, var(--lib-text) 8%, transparent); }
  .lib-ugc[data-ratio='portrait'] .lib-ugc__media { aspect-ratio: 4 / 5; }
  .lib-ugc__img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1); }
  svg.lib-ugc__img { fill: color-mix(in srgb, var(--lib-text) 22%, transparent); }

  .lib-ugc__caption {
    position: absolute;
    inset: auto 0 0;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.4rem;
    padding: 0.6rem;
    pointer-events: none;
  }
  .lib-ugc__credit {
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
    background: rgb(0 0 0 / 0.55);
    color: #fff;
    font-size: 0.75rem;
    line-height: 1.3;
  }
  .lib-ugc__chip {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.35rem;
    max-width: 100%;
    min-height: 2.25rem;
    padding: 0.45rem 0.75rem;
    border-radius: 999px;
    background: var(--lib-chip);
    color: var(--lib-chip-text);
    font-size: 0.8125rem;
    line-height: 1.25;
    text-decoration: none;
    box-shadow: 0 2px 10px rgb(0 0 0 / 0.12);
    pointer-events: auto;
  }
  .lib-ugc__prefix { opacity: 0.75; }
  .lib-ugc__product { font-weight: 600; }
  .lib-ugc__price { opacity: 0.8; }
  .lib-ugc__chip:hover .lib-ugc__product { text-decoration: underline; text-underline-offset: 0.2em; }
  .lib-ugc__chip:focus-visible { outline: 2px solid var(--lib-accent); outline-offset: 2px; }
  @media (max-width: 749px) {
    .lib-ugc__prefix,
    .lib-ugc__price { display: none; }
  }

  .lib-ugc__more { display: flex; justify-content: center; margin-top: clamp(1.5rem, 3vw, 2.25rem); }

  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .lib-ugc[data-animate] .lib-ugc__figure:hover .lib-ugc__img { transform: scale(1.04); }
  }
  @media (prefers-reduced-motion: reduce) {
    .lib-ugc__img { transition: none; }
  }
{% endstylesheet %}

{% schema %}
{
  "name": "Lib · UGC gallery",
  "tag": "section",
  "class": "lib-section",
  "max_blocks": 24,
  "settings": [
    { "type": "paragraph", "content": "Upload photos customers shared with you, with their permission. Nothing loads from Instagram or another service." },
    { "type": "header", "content": "Content" },
    { "type": "inline_richtext", "id": "heading", "label": "Heading", "default": "In your homes" },
    {
      "type": "select",
      "id": "heading_tag",
      "label": "Heading tag",
      "info": "Use H1 only when this is the page's main heading.",
      "options": [
        { "value": "h1", "label": "H1" },
        { "value": "h2", "label": "H2" },
        { "value": "h3", "label": "H3" },
        { "value": "p", "label": "Paragraph" }
      ],
      "default": "h2"
    },
    {
      "type": "select",
      "id": "heading_size",
      "label": "Heading size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" }
      ],
      "default": "medium"
    },
    { "type": "richtext", "id": "text", "label": "Intro text" },
    { "type": "text", "id": "button_label", "label": "Button text" },
    { "type": "url", "id": "button_url", "label": "Button link" },
    {
      "type": "select",
      "id": "button_style",
      "label": "Button style",
      "options": [
        { "value": "primary", "label": "Solid" },
        { "value": "outline", "label": "Outline" },
        { "value": "text", "label": "Text link" }
      ],
      "default": "outline"
    },
    { "type": "checkbox", "id": "button_new_tab", "label": "Open button link in a new tab", "default": false },

    { "type": "header", "content": "Product links" },
    { "type": "checkbox", "id": "show_product", "label": "Show the product in each photo", "default": true },
    { "type": "text", "id": "product_prefix", "label": "Text before the product name", "info": "Hidden on mobile to save space.", "default": "Shop" },
    { "type": "checkbox", "id": "show_price", "label": "Show price", "info": "Hidden on mobile to save space.", "default": true },

    { "type": "header", "content": "Layout" },
    { "type": "range", "id": "columns", "label": "Columns on desktop", "min": 2, "max": 6, "step": 1, "default": 3 },
    { "type": "range", "id": "columns_mobile", "label": "Columns on mobile", "min": 1, "max": 3, "step": 1, "default": 2 },
    {
      "type": "select",
      "id": "image_ratio",
      "label": "Photo shape",
      "options": [
        { "value": "square", "label": "Square" },
        { "value": "portrait", "label": "Portrait (4:5)" }
      ],
      "default": "square"
    },
    { "type": "range", "id": "gap", "label": "Space between photos", "min": 0, "max": 24, "step": 2, "unit": "px", "default": 8 },
    { "type": "range", "id": "radius", "label": "Corner radius", "min": 0, "max": 24, "step": 2, "unit": "px", "default": 10 },
    {
      "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": "Heading alignment on desktop",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" }
      ],
      "default": "center"
    },
    {
      "type": "select",
      "id": "text_alignment_mobile",
      "label": "Heading alignment on mobile",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" }
      ],
      "default": "left"
    },

    { "type": "header", "content": "Colors" },
    { "type": "color", "id": "color_bg", "label": "Background", "default": "#FFFFFF" },
    { "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": "Accent (button, focus)", "default": "#7A5A3A" },
    { "type": "color", "id": "color_accent_text", "label": "Text on accent", "default": "#FFFFFF" },
    { "type": "color", "id": "color_chip", "label": "Product label background", "default": "#FFFFFF" },
    { "type": "color", "id": "color_chip_text", "label": "Product label text", "default": "#1F1B17" },

    { "type": "header", "content": "Spacing and visibility" },
    { "type": "range", "id": "padding_top", "label": "Top padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 64 },
    { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 64 },
    { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 40 },
    { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 40 },
    {
      "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": "Zoom photos slightly on hover", "info": "Never when reduced motion is on.", "default": true }
  ],
  "blocks": [
    {
      "type": "photo",
      "name": "Photo",
      "settings": [
        { "type": "image_picker", "id": "image", "label": "Photo", "info": "Set the alt text in the image's details." },
        { "type": "image_picker", "id": "image_mobile", "label": "Mobile photo", "info": "Optional. Below 750px." },
        { "type": "text", "id": "credit", "label": "Credit", "info": "Optional, for example the customer's first name or handle, with their permission." },
        { "type": "product", "id": "product", "label": "Product in the photo" }
      ]
    }
  ],
  "presets": [
    {
      "name": "Lib · UGC gallery",
      "blocks": [{ "type": "photo" }, { "type": "photo" }, { "type": "photo" }, { "type": "photo" }, { "type": "photo" }, { "type": "photo" }]
    }
  ]
}
{% endschema %}
```

### snippets/lib-image.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{% doc %}
  Responsive image with optional art direction: a separate mobile image (below 750px),
  each honouring its own focal point from the theme editor. Falls back to a placeholder.

  @param {image} [image] - Desktop image (also used on mobile when no mobile image is set)
  @param {image} [image_mobile] - Mobile image, below 750px
  @param {string} [class] - Class for the img element
  @param {string} [sizes] - sizes attribute for the desktop image (default 100vw)
  @param {boolean} [eager] - Load immediately with high fetch priority (use for the first sections on a page)
  @param {string} [placeholder] - placeholder_svg_tag name when no image is set (default 'lifestyle-1')

  @example
  {% render 'lib-image', image: section.settings.image, image_mobile: section.settings.image_mobile, class: 'lib-hero__img', sizes: '(min-width: 990px) 50vw, 100vw', eager: true %}
{% enddoc %}

{%- liquid
  assign desktop = image
  if desktop == blank
    assign desktop = image_mobile
  endif
  assign img_sizes = sizes | default: '100vw'
  assign img_loading = 'lazy'
  assign img_priority = 'auto'
  if eager
    assign img_loading = 'eager'
    assign img_priority = 'high'
  endif
  assign art = false
  if image != blank and image_mobile != blank
    assign art = true
  endif
-%}

{%- if desktop != blank -%}
  <picture
    class="lib-picture{% if art %} lib-picture--art{% endif %}"
    {% if art %}
      style="--lib-pos-m: {{ image_mobile.presentation.focal_point | default: '50% 50%' }};"
    {% endif %}
  >
    {%- if art -%}
      <source
        media="(max-width: 749px)"
        srcset="
          {{ image_mobile | image_url: width: 375 }} 375w,
          {{ image_mobile | image_url: width: 750 }} 750w,
          {{ image_mobile | image_url: width: 1100 }} 1100w,
          {{ image_mobile | image_url: width: 1500 }} 1500w
        "
        sizes="100vw"
        width="{{ image_mobile.width }}"
        height="{{ image_mobile.height }}"
      >
    {%- endif -%}
    {{
      desktop
      | image_url: width: 2400
      | image_tag:
        class: class,
        loading: img_loading,
        fetchpriority: img_priority,
        sizes: img_sizes,
        widths: '600, 900, 1200, 1600, 2000, 2400'
    }}
  </picture>
{%- else -%}
  {{ placeholder | default: 'lifestyle-1' | placeholder_svg_tag: class }}
{%- endif -%}

{% stylesheet %}
  .lib-picture { display: contents; }
  @media (max-width: 749px) {
    /* image_tag sets the desktop focal point inline; the mobile image needs its own. */
    .lib-picture--art img { object-position: var(--lib-pos-m) !important; }
  }
{% endstylesheet %}
```

### snippets/lib-button.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{% doc %}
  Animated call-to-action link. Light sweep on hover, arrow slides right.
  Colors come from the parent section's --lib-accent / --lib-accent-text / --lib-text vars.
  Inspired by Uiverse.io button patterns; rewritten for themes, no dependencies.

  @param {string} label - Button text
  @param {string} [url] - Link target; renders a disabled-looking span when blank
  @param {string} [style] - 'primary' (default), 'outline' or 'text'
  @param {boolean} [new_tab] - Open the link in a new tab
  @param {boolean} [arrow] - Show the trailing arrow (default true)

  @example
  {% render 'lib-button', label: section.settings.button_label, url: section.settings.button_url, style: 'outline' %}
{% enddoc %}

{%- liquid
  assign btn_style = style | default: 'primary'
  assign show_arrow = true
  if arrow == false
    assign show_arrow = false
  endif
-%}

{%- unless label == blank -%}
{%- capture inner -%}
  <span class="lib-btn__label">{{ label | escape }}</span>
  {%- if show_arrow -%}
    <svg class="lib-btn__arrow" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">
      <path d="M3 8h9M8.5 4.5 12 8l-3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
  {%- endif -%}
{%- endcapture -%}

{%- if url != blank -%}
  <a
    class="lib-btn lib-btn--{{ btn_style }}"
    href="{{ url }}"
    {% if new_tab %}
      target="_blank" rel="noopener"
    {% endif %}
  >
    {{- inner -}}
  </a>
{%- else -%}
  <span class="lib-btn lib-btn--{{ btn_style }}" aria-disabled="true">{{ inner }}</span>
{%- endif -%}
{%- endunless -%}

{% stylesheet %}
  .lib-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.85em 1.5em;
    border-radius: var(--lib-radius, 999px);
    font: inherit;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    overflow: hidden;
    isolation: isolate;
    transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
  }
  .lib-btn--primary {
    background: var(--lib-accent, #111);
    color: var(--lib-accent-text, #fff);
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.12);
  }
  .lib-btn--outline {
    background: transparent;
    color: var(--lib-text, #111);
    box-shadow: inset 0 0 0 1.5px currentColor;
  }
  .lib-btn--text {
    padding-inline: 0;
    background: none;
    color: var(--lib-text, #111);
    text-decoration: underline;
    text-underline-offset: 0.3em;
    overflow: visible;
  }
  .lib-btn--text::before { display: none; }
  .lib-btn--text:hover { transform: none; box-shadow: none; }
  .lib-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(110deg, transparent 30%, rgb(255 255 255 / 0.35) 50%, transparent 70%);
    transform: translateX(-120%);
    transition: transform 0.6s ease;
  }
  .lib-btn--outline::before {
    background: linear-gradient(110deg, transparent 30%, rgb(127 127 127 / 0.18) 50%, transparent 70%);
  }
  .lib-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px -8px rgb(0 0 0 / 0.35);
  }
  .lib-btn:hover::before { transform: translateX(120%); }
  .lib-btn__arrow { transition: transform 0.2s ease; }
  .lib-btn:hover .lib-btn__arrow { transform: translateX(3px); }
  .lib-btn:focus-visible {
    outline: 2px solid var(--lib-accent, #111);
    outline-offset: 3px;
  }
  .lib-btn[aria-disabled='true'] { pointer-events: none; }
  @media (prefers-reduced-motion: reduce) {
    .lib-btn, .lib-btn::before, .lib-btn__arrow { transition: none; }
    .lib-btn:hover { transform: none; }
  }
{% endstylesheet %}
```

## 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.
