# Zaman çizelgesi: ücretsiz Shopify bölümü

> Marka hikâyeniz ya da bir süreç, çizgi üzerinde tarihli adımlarla: masaüstünde iki yanda, mobilde alt alta; görselli, bağlantılı. Yalnızca Liquid ve CSS.

Zaman çizelgesi, bir markanın geçmişini ya da bir sürecin aşamalarını bir çizgi üzerinde tarihli adımlarla anlatan ücretsiz bir Shopify bölümüdür. Masaüstünde adımlar ortadaki çizginin iki yanına dönüşümlü olarak dizilir ya da tek tarafta toplanır; mobilde her zaman tek tarafta, alt alta görünür. Her adımda bir tarih etiketi (2019 ya da 2021 Baharı gibi serbest metin), başlık, metin, ayrı mobil görseli ve odak noktaları olan isteğe bağlı bir görsel ile isteğe bağlı bir bağlantı bulunur. Online Store 2.0 temaları için JavaScript kullanmadan, yalnızca Liquid ve CSS ile yazılmış sıralı bir listedir.

- **Kategori:** İçerik ve hikâye anlatımı
- **Kullanıldığı yerler:** Hakkımızda, Açılış sayfaları, Ana sayfa
- **Okuduğu veri:** Yalnızca içerik
- **Boyut:** 3 dosyada 21 KB, JavaScript yok
- **Lisans:** MIT, © 2026 Lintel
- **Sayfa:** https://lintelagency.com/tr/kaynaklar/shopify-bolumleri/zaman-cizelgesi
- **Canlı demo:** https://lintelagency.com/resources/shopify-sections/demo/lib-timeline.html
- **Eklenme tarihi:** 2026-11-02

## Ne işe yarar

- Hakkımızda sayfasında, ilk üründen bugüne markanın hikâyesi
- Siparişe özel üretilen bir ürünün siparişten teslimata kadar nasıl hazırlandığı
- Bir iş birliğinin, restorasyonun ya da yenilemenin adım adım anlatımı

## Tema düzenleyici ayarları

Bölüm tema düzenleyicide “Lib · Timeline” 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 | Our story so far |  |
| `heading_tag` | `select` | Heading tag | h2 | `h1`, `h2`, `h3`, `p` |
| `heading_size` | `select` | Heading size | medium | `small`, `medium`, `large` |
| `text` | `richtext` | Intro text | – |  |

### Layout

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `layout` | `select` | Layout on desktop | alternate | `alternate`, `single` |
| `item_style` | `select` | Milestone style | card | `plain`, `card` |
| `image_ratio` | `select` | Image shape | standard | `standard`, `landscape`, `square` |
| `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 | #FAF6F1 |  |
| `color_bg_gradient` | `color_background` | Background gradient | – |  |
| `color_text` | `color` | Text | #1F1B17 |  |
| `color_accent` | `color` | Accent (markers, dates) | #7A5A3A |  |
| `color_accent_text` | `color` | Text on accent | #FFFFFF |  |
| `color_line` | `color` | Line | #DCCFBF |  |
| `color_card` | `color` | Card background | #FFFFFF |  |

### Spacing and visibility

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `padding_top` | `range` | Top padding on desktop | `80` | 0–200 px, step 4 |
| `padding_bottom` | `range` | Bottom padding on desktop | `80` | 0–200 px, step 4 |
| `padding_top_mobile` | `range` | Top padding on mobile | `48` | 0–160 px, step 4 |
| `padding_bottom_mobile` | `range` | Bottom padding on mobile | `48` | 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` | Fade milestones in on scroll | `true` |  |

## Bloklar

Toplamda en fazla 16 blok.

### Milestone (`milestone`)

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `date` | `text` | Date | 2019 |  |
| `title` | `text` | Title | Milestone title |  |
| `text` | `richtext` | Text | `<p>A sentence or two about what happened and why it mattered.</p>` |  |
| `image` | `image_picker` | Image | – |  |
| `image_mobile` | `image_picker` | Mobile image | – |  |
| `link_label` | `text` | Link text | – |  |
| `link_url` | `url` | Link | – |  |
| `link_new_tab` | `checkbox` | Open link in a new tab | `false` |  |

## 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-timeline.liquid` adında yeni bir dosya ekleyin, aşağıdaki kaynak koddan `sections/lib-timeline.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 · Timeline** 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-timeline.liquid https://lintelagency.com/resources/shopify-sections/files/lib-timeline.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-timeline.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-timeline.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-timeline.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

### Kaç adım ekleyebilirim?

En çok 16; her biri tema düzenleyicide sırasını değiştirebileceğiniz bir bloktur. Tarih etiketi serbest metindir; bir yıl, bir mevsim ya da "1. adım" olabilir.

### Mobilde nasıl görünüyor?

Masaüstü düzeniniz ne olursa olsun çizgi sola geçer, adımlar da sağında alt alta dizilir. Her adıma ayrı bir mobil görsel de verebilirsiniz.

### Ekran okuyucular ve arama motorları okuyabiliyor mu?

Evet. Adımlar HTML’de, sizin belirlediğiniz sırayla ve gerçek başlıklarla oluşturulmuş sıralı bir listedir; çizgi ve işaretler yalnızca görsel süslemedir. JavaScript yoktur.

### Adımlar kaydırınca belirebilir mi?

Evet; hareket ayarını açarsanız, kaydırmaya bağlı CSS animasyonlarını destekleyen tarayıcılarda. Ziyaretçi hareketin azaltılmasını istediğinde animasyon hiç çalışmaz; içerik animasyon olmadan da görünür.

## Kaynak kod

### sections/lib-timeline.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{%- comment -%}
  Timeline: dated milestones for a brand's story or a process, as an ordered list on a line.
  On desktop the milestones alternate either side of the line or sit on one side; on mobile they
  always stack on one side. Each milestone has a date label, title, text, optional image (separate
  mobile image, focal points) and an optional link. 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 item_tag = 'h3'
  if heading_tag == 'h3' or heading_tag == 'p'
    assign item_tag = 'h4'
  endif
-%}

<div
  class="lib-timeline lib-timeline--{{ s.section_width }}"
  {% if s.anchor_id != blank %}
    id="{{ s.anchor_id | handleize }}"
  {% endif %}
  data-show="{{ s.show_on }}"
  data-layout="{{ s.layout }}"
  data-style="{{ s.item_style }}"
  {% 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-line: {{ s.color_line }};
    --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-timeline__inner">
    {%- if s.heading != blank or s.text != blank -%}
      <header class="lib-timeline__header" data-align="{{ s.text_alignment }}" data-align-m="{{ s.text_alignment_mobile }}">
        {%- if s.heading != blank -%}
          <{{ heading_tag }} class="lib-timeline__heading lib-timeline__heading--{{ s.heading_size }}">
            {{- s.heading -}}
          </{{ heading_tag }}>
        {%- endif -%}
        {%- if s.text != blank -%}
          <div class="lib-timeline__text">{{ s.text }}</div>
        {%- endif -%}
      </header>
    {%- endif -%}

    {%- if section.blocks.size > 0 -%}
      <ol class="lib-timeline__list" role="list">
        {%- for block in section.blocks -%}
          {%- assign b = block.settings -%}
          <li class="lib-timeline__item{% if b.image != blank or b.image_mobile != blank %} has-image{% endif %}" {{ block.shopify_attributes }}>
            <span class="lib-timeline__marker" aria-hidden="true"></span>
            <div class="lib-timeline__card">
              {%- if b.date != blank -%}
                <p class="lib-timeline__date">{{ b.date | escape }}</p>
              {%- endif -%}
              {%- if b.title != blank -%}
                <{{ item_tag }} class="lib-timeline__title">{{ b.title | escape }}</{{ item_tag }}>
              {%- endif -%}
              {%- if b.image != blank or b.image_mobile != blank -%}
                <div class="lib-timeline__media" data-ratio="{{ s.image_ratio }}">
                  {%- render 'lib-image', image: b.image, image_mobile: b.image_mobile, class: 'lib-timeline__img', sizes: '(min-width: 990px) 480px, 90vw' -%}
                </div>
              {%- endif -%}
              {%- if b.text != blank -%}
                <div class="lib-timeline__body">{{ b.text }}</div>
              {%- endif -%}
              {%- if b.link_label != blank -%}
                <div class="lib-timeline__link">
                  {%- render 'lib-button', label: b.link_label, url: b.link_url, style: 'text', new_tab: b.link_new_tab, arrow: true -%}
                </div>
              {%- endif -%}
            </div>
          </li>
        {%- endfor -%}
      </ol>
    {%- endif -%}
  </div>
</div>

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

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

  /* One side: line on the left. Mobile always uses this. */
  .lib-timeline__list {
    --lib-gutter: 2.25rem;
    position: relative;
    display: grid;
    gap: clamp(1.75rem, 4vw, 2.75rem);
    margin: 0;
    padding: 0 0 0 var(--lib-gutter);
    list-style: none;
  }
  .lib-timeline__list::before {
    content: '';
    position: absolute;
    top: 0.5rem;
    bottom: 0.5rem;
    left: calc(0.5rem - 1px);
    width: 2px;
    background: var(--lib-line);
  }
  .lib-timeline__item { position: relative; min-width: 0; }
  .lib-timeline__marker {
    position: absolute;
    top: 0.3rem;
    left: calc(var(--lib-gutter) * -1);
    width: 1rem;
    height: 1rem;
    border: 3px solid var(--lib-bg);
    border-radius: 50%;
    background: var(--lib-accent);
    box-shadow: 0 0 0 2px var(--lib-accent);
  }
  .lib-timeline__card { max-width: 34rem; }
  .lib-timeline[data-style='card'] .lib-timeline__card {
    padding: clamp(1.125rem, 2.5vw, 1.75rem);
    border-radius: 14px;
    background: var(--lib-card);
  }
  .lib-timeline__date {
    display: inline-block;
    margin: 0 0 0.5rem;
    padding: 0.2rem 0.65rem;
    border-radius: 999px;
    background: var(--lib-accent);
    color: var(--lib-accent-text);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.02em;
  }
  .lib-timeline__title { margin: 0; font-size: clamp(1.125rem, 1.6vw, 1.3125rem); line-height: 1.3; }
  .lib-timeline__media {
    overflow: hidden;
    margin-top: 0.875rem;
    border-radius: 10px;
    aspect-ratio: 4 / 3;
    background: color-mix(in srgb, var(--lib-text) 6%, transparent);
  }
  .lib-timeline__media[data-ratio='landscape'] { aspect-ratio: 16 / 9; }
  .lib-timeline__media[data-ratio='square'] { aspect-ratio: 1; }
  .lib-timeline__img { display: block; width: 100%; height: 100%; object-fit: cover; }
  .lib-timeline__body { margin-top: 0.625rem; font-size: 0.9375rem; line-height: 1.6; opacity: 0.85; }
  .lib-timeline__body > :first-child { margin-top: 0; }
  .lib-timeline__body > :last-child { margin-bottom: 0; }
  .lib-timeline__link { margin-top: 0.625rem; font-size: 0.9375rem; }

  /* Alternating: the line runs down the middle; milestones take turns on either side, the right
     column a little lower, so each pair overlaps instead of leaving a gap the height of a card. */
  @media (min-width: 750px) {
    .lib-timeline[data-layout='alternate'] .lib-timeline__list {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      column-gap: calc(var(--lib-gutter) * 2);
      padding-left: 0;
    }
    .lib-timeline[data-layout='alternate'] .lib-timeline__list::before { left: calc(50% - 1px); }
    .lib-timeline[data-layout='alternate'] .lib-timeline__item { grid-column: 1; }
    .lib-timeline[data-layout='alternate'] .lib-timeline__card { margin-left: auto; text-align: right; }
    .lib-timeline[data-layout='alternate'] .lib-timeline__marker { left: auto; right: calc(var(--lib-gutter) * -1 - 0.5rem); }
    .lib-timeline[data-layout='alternate'] .lib-timeline__item:nth-child(even) {
      grid-column: 2;
      margin-top: clamp(3rem, 9vw, 8rem);
    }
    .lib-timeline[data-layout='alternate'] .lib-timeline__item:nth-child(even) .lib-timeline__card { margin-left: 0; text-align: left; }
    .lib-timeline[data-layout='alternate'] .lib-timeline__item:nth-child(even) .lib-timeline__marker { right: auto; left: calc(var(--lib-gutter) * -1 - 0.5rem); }
  }

  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .lib-timeline[data-animate] .lib-timeline__card {
        animation: lib-timeline-rise linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 55%;
      }
    }
  }
  @keyframes lib-timeline-rise {
    from { opacity: 0; transform: translateY(20px); }
  }
{% endstylesheet %}

{% schema %}
{
  "name": "Lib · Timeline",
  "tag": "section",
  "class": "lib-section",
  "max_blocks": 16,
  "settings": [
    { "type": "header", "content": "Content" },
    { "type": "inline_richtext", "id": "heading", "label": "Heading", "default": "Our story so far" },
    {
      "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": "header", "content": "Layout" },
    {
      "type": "select",
      "id": "layout",
      "label": "Layout on desktop",
      "info": "Mobile always shows one side.",
      "options": [
        { "value": "alternate", "label": "Alternating sides" },
        { "value": "single", "label": "One side" }
      ],
      "default": "alternate"
    },
    {
      "type": "select",
      "id": "item_style",
      "label": "Milestone style",
      "options": [
        { "value": "plain", "label": "Plain" },
        { "value": "card", "label": "Card" }
      ],
      "default": "card"
    },
    {
      "type": "select",
      "id": "image_ratio",
      "label": "Image shape",
      "options": [
        { "value": "standard", "label": "4:3" },
        { "value": "landscape", "label": "16:9" },
        { "value": "square", "label": "Square" }
      ],
      "default": "standard"
    },
    {
      "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": "#FAF6F1" },
    { "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 (markers, dates)", "default": "#7A5A3A" },
    { "type": "color", "id": "color_accent_text", "label": "Text on accent", "default": "#FFFFFF" },
    { "type": "color", "id": "color_line", "label": "Line", "default": "#DCCFBF" },
    { "type": "color", "id": "color_card", "label": "Card background", "default": "#FFFFFF" },

    { "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": 80 },
    { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 80 },
    { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 48 },
    { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 48 },
    {
      "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": "Fade milestones in on scroll", "info": "Only in browsers that support scroll-driven animations; never when reduced motion is on.", "default": true }
  ],
  "blocks": [
    {
      "type": "milestone",
      "name": "Milestone",
      "settings": [
        { "type": "text", "id": "date", "label": "Date", "info": "Any label: 2019, Spring 2021, Step 1…", "default": "2019" },
        { "type": "text", "id": "title", "label": "Title", "default": "Milestone title" },
        { "type": "richtext", "id": "text", "label": "Text", "default": "<p>A sentence or two about what happened and why it mattered.</p>" },
        { "type": "image_picker", "id": "image", "label": "Image" },
        { "type": "image_picker", "id": "image_mobile", "label": "Mobile image", "info": "Optional. Below 750px." },
        { "type": "text", "id": "link_label", "label": "Link text" },
        { "type": "url", "id": "link_url", "label": "Link" },
        { "type": "checkbox", "id": "link_new_tab", "label": "Open link in a new tab", "default": false }
      ]
    }
  ],
  "presets": [
    {
      "name": "Lib · Timeline",
      "blocks": [
        { "type": "milestone", "settings": { "date": "2019", "title": "The first wheel" } },
        { "type": "milestone", "settings": { "date": "2021", "title": "Our own kiln" } },
        { "type": "milestone", "settings": { "date": "2024", "title": "The studio shop opens" } }
      ]
    }
  ]
}
{% 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.
