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

> Solma ya da kaydırmayla dönen en fazla altı mesajlı ince çubuk; isteğe bağlı oklar, ikonlar, bağlantılar ve her kampanyayı hatırlayan kapat düğmesi.

Duyuru çubuğu, teslimat eşikleri ya da süren bir kampanya gibi kısa mağaza mesajları için ücretsiz bir Shopify bölümüdür: tek bir mesaj gösterin ya da en fazla altı mesajı solma veya kaydırmayla ve isteğe bağlı oklarla döndürün. Ziyaretçiler onu kapatabilir ve kampanya sürümünü değiştirene kadar kapalı kalır; Online Store 2.0 temalarında uygulama olmadan çalışır.

- **Kategori:** Dönüşüm ve kampanyalar
- **Kullanıldığı yerler:** Tüm sayfalar, Ana sayfa, Açılış sayfaları
- **Okuduğu veri:** Yalnızca içerik
- **Boyut:** 1 dosyada 23 KB, küçük bir betikle
- **Lisans:** MIT, © 2026 Lintel
- **Sayfa:** https://lintelagency.com/tr/kaynaklar/shopify-bolumleri/duyuru-cubugu
- **Canlı demo:** https://lintelagency.com/resources/shopify-sections/demo/lib-announcement-bar.html
- **Eklenme tarihi:** 2026-10-02

## Ne işe yarar

- Her sayfada üst bilginin üstünde ücretsiz teslimat eşiği ve iade mesajı
- "Pazar günü bitiyor" notu ve indirim koleksiyonuna bağlantıyla sezonluk kampanya
- Bir açılış sayfasının en üstünde kapatılabilir lansman duyurusu

## Tema düzenleyici ayarları

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

### Behaviour

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `mode` | `select` | Mode | rotating | `static`, `rotating` |
| `transition` | `select` | Transition | slide | `fade`, `slide` |
| `interval` | `range` | Time per message | `5` | 3–12 s, step 1 |
| `show_arrows` | `checkbox` | Show previous and next arrows | `true` |  |
| `dismissible` | `checkbox` | Visitors can close the bar | `false` |  |
| `dismiss_version` | `text` | Campaign version | 1 |  |
| `sticky` | `checkbox` | Stick to the top while scrolling | `false` |  |

### Layout

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `text_size` | `select` | Text size | medium | `small`, `medium`, `large` |
| `text_alignment` | `text_alignment` | Alignment on desktop | center |  |
| `text_alignment_mobile` | `select` | Alignment on mobile | center | `left`, `center` |
| `section_width` | `select` | Width | page | `page`, `full` |

### Colors

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `color_bg` | `color` | Background | #1C1917 |  |
| `color_bg_gradient` | `color_background` | Background gradient | – |  |
| `color_text` | `color` | Text | #FAFAF9 |  |
| `color_link` | `color` | Links | #F5D0A9 |  |
| `border_bottom` | `checkbox` | Bottom border | `false` |  |
| `color_border` | `color` | Border | #44403C |  |

### Spacing and visibility

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

## Bloklar

Toplamda en fazla 6 blok.

### Message (`message`, en fazla 6)

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `message` | `inline_richtext` | Message | Free delivery on orders over $75 |  |
| `icon` | `select` | Icon | none | `none`, `truck`, `gift`, `tag`, `star`, `leaf`, `clock`, `sparkle`, `return`, `emoji` |
| `emoji` | `text` | Emoji | ✨ |  |
| `link` | `url` | Link | – |  |
| `link_label` | `text` | Link label | – |  |
| `ends_text` | `text` | Ends note | – |  |

## 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-announcement-bar.liquid` adında yeni bir dosya ekleyin, aşağıdaki kaynak koddan `sections/lib-announcement-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 · Announcement 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-announcement-bar.liquid https://lintelagency.com/resources/shopify-sections/files/lib-announcement-bar.liquid
shopify theme push --theme <unpublished-theme-id> --only sections/lib-announcement-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-announcement-bar.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-announcement-bar.liquid): `sections/` klasörüne

## Sık sorulan sorular

### Kapat düğmesi ziyaretçileri nasıl hatırlar?

Ziyaretçi çubuğu kapattığında, bölüm kimliğinden ve belirlediğiniz kampanya sürümünden oluşan bir anahtar tarayıcısının local storage’ına kaydedilir ve çubuk sonraki sayfalarda gizli kalır. Çubuğu herkese yeniden göstermek için kampanya sürümünü değiştirin. Tarayıcı depolamayı engellerse çubuk yine o sayfa görüntülemesi için kapanır. Tema düzenleyicide çubuk yüklenirken asla gizlenmez.

### Çubuk düzen kaymasına yol açar mı?

Hayır. Tüm mesajlar tek bir grid hücresini paylaşır; böylece çubuk ilk çizimden itibaren en uzun mesaj kadar yüksektir ve döndürmeyi başlatan script yüksekliğini değiştirmez. Ziyaretçinin daha önce kapattığı bir çubuk, ayrıştırılırken çalışan küçük bir satır içi script ile gizlenir.

### Dönen çubuk erişilebilir mi?

Mesajlar etiketli slaytlarla bir carousel bölgesi olarak işaretlenmiştir; gizli slaytlara odaklanılamaz ve dönerken ekran okuyucular kesilmez. Döndürme fare üzerindeyken, klavye odağındayken ve sekme gizliyken durur; oklar gerçek düğmelerdir. Azaltılmış hareket açıkken dönmez ve oklar mesajları animasyonsuz değiştirir.

### Geri sayım ekleyebilir miyim?

Bu bölümde hayır. Her mesaj "Pazar günü bitiyor" gibi düz metin olan kısa bir bitiş notu taşıyabilir. Canlı bir sayaç için aynı kütüphanedeki Geri sayım banner bölümünü kullanın.

### Çubuk kaydırırken görünür kalabilir mi?

Evet. Sabit (sticky) seçeneğini açın; bölüm pencerenin üstüne yapışır. Temanızda da sabit bir üst bilgi varsa ikisinin üst üste binmediğini kontrol edin.

## Kaynak kod

### sections/lib-announcement-bar.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{%- comment -%}
  Announcement bar: one static message, or several that rotate (fade or slide) with optional arrows.
  Each message has an optional icon or emoji, link and short "ends" note. Dismissible with a close
  button that is remembered per browser; change the campaign version to show it again.
  All messages share one grid cell, so the bar is as tall as its longest message from the first paint
  and nothing shifts when the script starts. Optional sticky at the top of the page.
  Depends on: nothing.
{%- endcomment -%}

{%- liquid
  assign s = section.settings
  assign count = section.blocks.size
  assign rotating = false
  if s.mode == 'rotating' and count > 1
    assign rotating = true
  endif
  assign arrows = false
  if rotating and s.show_arrows
    assign arrows = true
  endif
  assign version = s.dismiss_version | default: '1' | handleize
  assign dismiss_key = 'lib-announce:' | append: section.id | append: ':' | append: version
-%}

{%- if s.sticky -%}
  <style>
    #shopify-section-{{ section.id }} { position: sticky; top: 0; z-index: 40; }
  </style>
{%- endif -%}

<div
  class="lib-announce lib-announce--{{ s.section_width }} lib-announce--{{ s.text_size }}"
  {% if s.anchor_id != blank %}
    id="{{ s.anchor_id | handleize }}"
  {% endif %}
  data-show="{{ s.show_on }}"
  data-transition="{{ s.transition }}"
  {% if s.border_bottom %}
    data-border
  {% endif %}
  {% if s.dismissible %}
    data-dismissible
  {% 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_link }};
    --lib-border: {{ s.color_border }};
    --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;
  "
>
  <lib-announcement-bar
    class="lib-announce__inner"
    data-align="{{ s.text_alignment }}"
    data-align-m="{{ s.text_alignment_mobile }}"
    {% if rotating %}
      data-rotating data-interval="{{ s.interval }}"
    {% endif %}
    {% if s.dismissible %}
      data-dismiss-key="{{ dismiss_key }}"
    {% endif %}
  >
    {%- if arrows -%}
      <button type="button" class="lib-announce__arrow" data-dir="-1" aria-label="Previous announcement">
        <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M15 6l-6 6 6 6" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
      </button>
    {%- endif -%}

    <div
      class="lib-announce__viewport"
      {% if rotating %}
        role="region" aria-roledescription="carousel" aria-label="Announcements"
      {% endif %}
    >
      <div class="lib-announce__track"{% if rotating %} aria-live="off" data-track{% endif %}>
        {%- for block in section.blocks -%}
          {%- unless rotating or forloop.first -%}{%- continue -%}{%- endunless -%}
          {%- assign b = block.settings -%}
          {%- assign wrap_link = false -%}
          {%- if b.link != blank and b.link_label == blank -%}
            {%- unless b.message contains '<a' -%}
              {%- assign wrap_link = true -%}
            {%- endunless -%}
          {%- endif -%}
          <div
            class="lib-announce__slide"
            {% if rotating %}
              role="group" aria-roledescription="slide" aria-label="{{ forloop.index }} of {{ count }}" data-slide
              {% if forloop.first %}data-active{% else %}inert{% endif %}
            {% else %}
              data-active
            {% endif %}
            {{ block.shopify_attributes }}
          >
            {%- if wrap_link -%}<a class="lib-announce__wrap-link" href="{{ b.link }}">{%- endif -%}
            {%- if b.icon == 'emoji' and b.emoji != blank -%}
              <span class="lib-announce__emoji" aria-hidden="true">{{ b.emoji | escape }}</span>
            {%- elsif b.icon != 'none' and b.icon != 'emoji' -%}
              <svg class="lib-announce__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
                {%- case b.icon -%}
                  {%- when 'truck' -%}
                    <path d="M14 17V6H3v11h1.5"/><path d="M14 9h4l3 3.5V17h-1.5"/><path d="M9.5 17h5"/><circle cx="7" cy="17" r="2"/><circle cx="17" cy="17" r="2"/>
                  {%- when 'gift' -%}
                    <rect x="3" y="8" width="18" height="4" rx="1"/><path d="M5 12v9h14v-9"/><path d="M12 8v13"/><path d="M12 8C11 5 7 4 7 6.5S10 8 12 8zm0 0c1-3 5-4 5-1.5S14 8 12 8z"/>
                  {%- when 'tag' -%}
                    <path d="M3 12V4h8l10 10-8 8z"/><circle cx="7.5" cy="7.5" r="1.2"/>
                  {%- when 'star' -%}
                    <path d="m12 3 2.7 5.6 6.1.9-4.4 4.3 1 6.1L12 17l-5.4 2.9 1-6.1-4.4-4.3 6.1-.9z"/>
                  {%- when 'leaf' -%}
                    <path d="M5 19c0-8 5-14 15-15-1 10-7 15-15 15z"/><path d="m5 19 8-8"/>
                  {%- when 'clock' -%}
                    <circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>
                  {%- when 'sparkle' -%}
                    <path d="m12 3 1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z"/><path d="M19 16v4M17 18h4"/>
                  {%- when 'return' -%}
                    <path d="M9 14 4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 0 10h-4"/>
                {%- endcase -%}
              </svg>
            {%- endif -%}
            <span class="lib-announce__message">{{ b.message }}</span>
            {%- if wrap_link -%}</a>{%- endif -%}
            {%- if b.ends_text != blank -%}
              <span class="lib-announce__ends">{{ b.ends_text | escape }}</span>
            {%- endif -%}
            {%- if b.link != blank and b.link_label != blank -%}
              <a class="lib-announce__cta" href="{{ b.link }}">{{ b.link_label | escape }}</a>
            {%- endif -%}
          </div>
        {%- endfor -%}
      </div>
    </div>

    {%- if arrows -%}
      <button type="button" class="lib-announce__arrow" data-dir="1" aria-label="Next announcement">
        <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
      </button>
    {%- endif -%}

    {%- if s.dismissible -%}
      <button type="button" class="lib-announce__close" data-close aria-label="Close announcement">
        <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
      </button>
    {%- endif -%}
  </lib-announcement-bar>
</div>
{%- if s.dismissible and request.design_mode != true -%}
  <script>
    (function (bar) {
      try {
        var key = bar && bar.querySelector('[data-dismiss-key]');
        if (key && localStorage.getItem(key.dataset.dismissKey)) bar.hidden = true;
      } catch (e) {}
    })(document.currentScript && document.currentScript.previousElementSibling);
  </script>
{%- endif -%}

{% stylesheet %}
  .lib-announce {
    background-color: var(--lib-bg);
    background-image: var(--lib-bg-image, none);
    color: var(--lib-text);
    padding: var(--lib-pt) 1rem var(--lib-pb);
    font-size: 0.875rem;
    line-height: 1.4;
  }
  .lib-announce[hidden] { display: none; }
  .lib-announce--small { font-size: 0.8125rem; }
  .lib-announce--large { font-size: 1rem; }
  .lib-announce[data-border] { border-bottom: 1px solid var(--lib-border); }
  @media (max-width: 749px) {
    .lib-announce { padding-top: var(--lib-pt-m); padding-bottom: var(--lib-pb-m); }
    .lib-announce[data-show='desktop'] { display: none; }
  }
  @media (min-width: 750px) {
    .lib-announce[data-show='mobile'] { display: none; }
  }

  .lib-announce__inner {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    max-width: 1200px;
    margin: 0 auto;
  }
  .lib-announce--full .lib-announce__inner { max-width: none; }
  /* Keep the message clear of the close button, on both sides so centred text stays centred. */
  .lib-announce[data-dismissible] .lib-announce__inner { padding-inline: 2.25rem; }

  .lib-announce__viewport { flex: 1; min-width: 0; overflow: hidden; overflow: clip; }
  /* Every message sits in the same cell: the bar reserves the tallest one's height. */
  .lib-announce__track { display: grid; }
  .lib-announce__slide {
    grid-area: 1 / 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    column-gap: 0.5em;
    row-gap: 0.15em;
    min-width: 0;
    text-align: left;
    visibility: hidden;
  }
  .lib-announce__slide[data-active] { visibility: visible; }
  .lib-announce__inner[data-align='center'] .lib-announce__slide { justify-content: center; text-align: center; }
  .lib-announce__inner[data-align='right'] .lib-announce__slide { justify-content: flex-end; text-align: right; }
  @media (max-width: 749px) {
    .lib-announce__inner[data-align-m='left'] .lib-announce__slide { justify-content: flex-start; text-align: left; }
    .lib-announce__inner[data-align-m='center'] .lib-announce__slide { justify-content: center; text-align: center; }
  }

  .lib-announce__message > p { display: inline; margin: 0; }
  .lib-announce a { color: var(--lib-accent); text-underline-offset: 0.2em; }
  .lib-announce .lib-announce__wrap-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    color: inherit;
    text-decoration: none;
  }
  .lib-announce__wrap-link .lib-announce__message { text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); transition: text-decoration-color 0.2s; }
  .lib-announce__wrap-link:hover .lib-announce__message { text-decoration-color: currentColor; }
  .lib-announce__cta { font-weight: 600; text-decoration: underline; }
  .lib-announce__cta:hover { text-decoration-thickness: 2px; }
  .lib-announce__icon { flex: none; width: 1.15em; height: 1.15em; }
  .lib-announce__emoji { flex: none; line-height: 1; }
  .lib-announce__ends {
    padding: 0.1em 0.55em;
    border-radius: 999px;
    font-size: 0.85em;
    background: color-mix(in srgb, currentColor 14%, transparent);
    white-space: nowrap;
  }

  .lib-announce__arrow,
  .lib-announce__close {
    flex: none;
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    cursor: pointer;
    opacity: 0.75;
    transition: opacity 0.2s, background-color 0.2s;
  }
  .lib-announce__arrow:hover,
  .lib-announce__close:hover { opacity: 1; background: color-mix(in srgb, currentColor 10%, transparent); }
  .lib-announce__arrow svg,
  .lib-announce__close svg { width: 1rem; height: 1rem; }
  .lib-announce__close { position: absolute; inset-inline-end: 0; top: 50%; translate: 0 -50%; }
  .lib-announce__arrow:dir(rtl) svg { transform: scaleX(-1); }
  .lib-announce a:focus-visible,
  .lib-announce__arrow:focus-visible,
  .lib-announce__close:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; opacity: 1; }
{% endstylesheet %}

{% javascript %}
  if (!customElements.get('lib-announcement-bar')) {
    customElements.define(
      'lib-announcement-bar',
      class extends HTMLElement {
        connectedCallback() {
          if (this.ready) return;
          this.ready = true;
          this.bar = this.closest('.lib-announce');
          this.closeButton = this.querySelector('[data-close]');
          if (this.closeButton) this.closeButton.addEventListener('click', () => this.dismiss());

          this.slides = Array.from(this.querySelectorAll('[data-slide]'));
          this.track = this.querySelector('[data-track]');
          if (!this.hasAttribute('data-rotating') || this.slides.length < 2 || !this.track) return;

          this.index = Math.max(0, this.slides.findIndex((slide) => slide.hasAttribute('data-active')));
          this.delay = Math.max(2, Number(this.dataset.interval) || 5) * 1000;
          this.reduced = matchMedia('(prefers-reduced-motion: reduce)');
          this.hovered = false;
          this.focused = false;

          this.querySelectorAll('.lib-announce__arrow').forEach((button) =>
            button.addEventListener('click', () => this.go(this.index + Number(button.dataset.dir), Number(button.dataset.dir)))
          );
          this.addEventListener('mouseenter', () => { this.hovered = true; this.sync(); });
          this.addEventListener('mouseleave', () => { this.hovered = false; this.sync(); });
          this.addEventListener('focusin', () => { this.focused = true; this.sync(); });
          this.addEventListener('focusout', (event) => {
            if (this.contains(event.relatedTarget)) return;
            this.focused = false;
            this.sync();
          });
          this.onVisibility = () => this.sync();
          document.addEventListener('visibilitychange', this.onVisibility);
          this.onMotion = () => this.sync();
          this.reduced.addEventListener?.('change', this.onMotion);
          // Theme editor: show the selected message and hold it there.
          this.addEventListener('shopify:block:select', (event) => {
            const i = this.slides.indexOf(event.target);
            if (i > -1) this.go(i, 0, true);
            this.editing = true;
            this.sync();
          });
          this.addEventListener('shopify:block:deselect', () => { this.editing = false; this.sync(); });
          this.sync();
        }

        disconnectedCallback() {
          clearInterval(this.timer);
          this.timer = null;
          if (this.onVisibility) document.removeEventListener('visibilitychange', this.onVisibility);
          if (this.onMotion) this.reduced.removeEventListener?.('change', this.onMotion);
        }

        // Rotate only when nothing asks it to stop; screen readers hear changes only while it is still.
        sync() {
          const run = !this.reduced.matches && !this.hovered && !this.focused && !this.editing && !document.hidden;
          this.track.setAttribute('aria-live', run ? 'off' : 'polite');
          if (run && !this.timer) {
            this.timer = setInterval(() => this.go(this.index + 1, 1), this.delay);
          } else if (!run && this.timer) {
            clearInterval(this.timer);
            this.timer = null;
          }
        }

        go(target, dir = 1, instant = false) {
          const count = this.slides.length;
          const next = ((target % count) + count) % count;
          if (next === this.index) return;
          const from = this.slides[this.index];
          const to = this.slides[next];
          from.removeAttribute('data-active');
          from.setAttribute('inert', '');
          to.setAttribute('data-active', '');
          to.removeAttribute('inert');
          this.index = next;
          // Restart the countdown so a manual step gets a full interval.
          if (this.timer) {
            clearInterval(this.timer);
            this.timer = null;
            this.sync();
          }
          if (instant || this.reduced.matches || !from.animate) return;
          const slide = this.bar && this.bar.dataset.transition === 'slide';
          const rtl = getComputedStyle(this).direction === 'rtl' ? -1 : 1;
          const shift = (dir || 1) * rtl * 40;
          const timing = { duration: 450, easing: 'cubic-bezier(0.2, 0.7, 0.2, 1)' };
          from.animate(
            [
              { visibility: 'visible', opacity: 1, transform: 'none' },
              { visibility: 'visible', opacity: 0, transform: slide ? `translateX(${-shift}px)` : 'none' },
            ],
            timing
          );
          to.animate(
            [
              { opacity: 0, transform: slide ? `translateX(${shift}px)` : 'none' },
              { opacity: 1, transform: 'none' },
            ],
            timing
          );
        }

        dismiss() {
          const key = this.dataset.dismissKey;
          try {
            if (key) localStorage.setItem(key, '1');
          } catch (e) {}
          clearInterval(this.timer);
          this.timer = null;
          if (this.bar) this.bar.hidden = true;
        }
      }
    );
  }
{% endjavascript %}

{% schema %}
{
  "name": "Lib · Announcement bar",
  "tag": "section",
  "class": "lib-section",
  "max_blocks": 6,
  "settings": [
    { "type": "header", "content": "Behaviour" },
    {
      "type": "select",
      "id": "mode",
      "label": "Mode",
      "options": [
        { "value": "static", "label": "Static (first message only)" },
        { "value": "rotating", "label": "Rotate through messages" }
      ],
      "default": "rotating"
    },
    {
      "type": "select",
      "id": "transition",
      "label": "Transition",
      "options": [
        { "value": "fade", "label": "Fade" },
        { "value": "slide", "label": "Slide" }
      ],
      "default": "slide",
      "visible_if": "{{ section.settings.mode == 'rotating' }}"
    },
    {
      "type": "range",
      "id": "interval",
      "label": "Time per message",
      "info": "Rotation pauses on hover and keyboard focus, and is off when the visitor prefers reduced motion.",
      "min": 3,
      "max": 12,
      "step": 1,
      "unit": "s",
      "default": 5,
      "visible_if": "{{ section.settings.mode == 'rotating' }}"
    },
    { "type": "checkbox", "id": "show_arrows", "label": "Show previous and next arrows", "default": true, "visible_if": "{{ section.settings.mode == 'rotating' }}" },
    { "type": "checkbox", "id": "dismissible", "label": "Visitors can close the bar", "info": "Remembered in the visitor's browser.", "default": false },
    {
      "type": "text",
      "id": "dismiss_version",
      "label": "Campaign version",
      "info": "Change this (for example to \"spring-sale\") to show the bar again to visitors who closed it.",
      "default": "1",
      "visible_if": "{{ section.settings.dismissible }}"
    },
    { "type": "checkbox", "id": "sticky", "label": "Stick to the top while scrolling", "info": "Check it does not overlap a sticky header in your theme.", "default": false },

    { "type": "header", "content": "Layout" },
    {
      "type": "select",
      "id": "text_size",
      "label": "Text size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" }
      ],
      "default": "medium"
    },
    { "type": "text_alignment", "id": "text_alignment", "label": "Alignment on desktop", "default": "center" },
    {
      "type": "select",
      "id": "text_alignment_mobile",
      "label": "Alignment on mobile",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" }
      ],
      "default": "center"
    },
    {
      "type": "select",
      "id": "section_width",
      "label": "Width",
      "options": [
        { "value": "page", "label": "Page width" },
        { "value": "full", "label": "Full width" }
      ],
      "default": "page"
    },

    { "type": "header", "content": "Colors" },
    { "type": "color", "id": "color_bg", "label": "Background", "default": "#1C1917" },
    { "type": "color_background", "id": "color_bg_gradient", "label": "Background gradient", "info": "Optional. Covers the background color." },
    { "type": "color", "id": "color_text", "label": "Text", "default": "#FAFAF9" },
    { "type": "color", "id": "color_link", "label": "Links", "default": "#F5D0A9" },
    { "type": "checkbox", "id": "border_bottom", "label": "Bottom border", "default": false },
    { "type": "color", "id": "color_border", "label": "Border", "default": "#44403C", "visible_if": "{{ section.settings.border_bottom }}" },

    { "type": "header", "content": "Spacing and visibility" },
    { "type": "range", "id": "padding_top", "label": "Top padding on desktop", "min": 0, "max": 40, "step": 1, "unit": "px", "default": 10 },
    { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 40, "step": 1, "unit": "px", "default": 10 },
    { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 40, "step": 1, "unit": "px", "default": 8 },
    { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 40, "step": 1, "unit": "px", "default": 8 },
    {
      "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." }
  ],
  "blocks": [
    {
      "type": "message",
      "name": "Message",
      "limit": 6,
      "settings": [
        { "type": "inline_richtext", "id": "message", "label": "Message", "default": "Free delivery on orders over $75" },
        {
          "type": "select",
          "id": "icon",
          "label": "Icon",
          "options": [
            { "value": "none", "label": "None" },
            { "value": "truck", "label": "Delivery truck" },
            { "value": "gift", "label": "Gift" },
            { "value": "tag", "label": "Price tag" },
            { "value": "star", "label": "Star" },
            { "value": "leaf", "label": "Leaf" },
            { "value": "clock", "label": "Clock" },
            { "value": "sparkle", "label": "Sparkle" },
            { "value": "return", "label": "Returns" },
            { "value": "emoji", "label": "Emoji" }
          ],
          "default": "none"
        },
        { "type": "text", "id": "emoji", "label": "Emoji", "default": "✨", "visible_if": "{{ block.settings.icon == 'emoji' }}" },
        { "type": "url", "id": "link", "label": "Link" },
        {
          "type": "text",
          "id": "link_label",
          "label": "Link label",
          "info": "Optional. Leave empty to make the whole message the link.",
          "visible_if": "{{ block.settings.link != blank }}"
        },
        { "type": "text", "id": "ends_text", "label": "Ends note", "info": "Optional short note, for example \"Ends Sunday\". No timer." }
      ]
    }
  ],
  "presets": [
    {
      "name": "Lib · Announcement bar",
      "blocks": [
        { "type": "message", "settings": { "message": "Free delivery on orders over $75", "icon": "truck" } },
        { "type": "message", "settings": { "message": "<strong>Autumn edit:</strong> 20% off linen bedding", "icon": "tag", "link_label": "Shop the edit", "ends_text": "Ends Sunday" } },
        { "type": "message", "settings": { "message": "Gift wrapping is free on every order", "icon": "gift" } }
      ]
    }
  ]
}
{% 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.
