{%- comment -%} MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections {%- endcomment -%} {%- comment -%} Press quotes: short quotes from the press with each publication's logo (or its name), in a row of quote cards or as an "as seen in" rotator where the logos switch the quote. The rotator is a WAI-ARIA tabs pattern with optional autoplay that has a pause button, stops on hover and focus, and never runs when reduced motion is on. Without JavaScript every quote shows. Every quote, name and logo is the merchant's own: use only coverage you actually received. Depends on: nothing {%- endcomment -%} {%- liquid assign s = section.settings assign heading_tag = s.heading_tag | default: 'h2' assign rotator = false if s.layout == 'rotator' and section.blocks.size > 1 assign rotator = true endif -%}
{%- if s.heading != blank -%} <{{ heading_tag }} class="lib-press__heading lib-press__heading--{{ s.heading_size }}"> {{- s.heading -}} {%- endif -%}
{%- for block in section.blocks -%} {%- assign b = block.settings -%}
{%- if s.show_marks -%}{%- endif -%} {{- b.quote -}}
{%- capture source -%} {%- if b.logo != blank -%} {{ b.logo | image_url: width: 400 | image_tag: class: 'lib-press__logo', loading: 'lazy', alt: b.publication }} {%- else -%} {{ b.publication | escape }} {%- endif -%} {%- endcapture -%} {%- if b.link != blank -%} {{- source -}} {%- if b.new_tab and s.new_tab_label != blank -%} ({{ s.new_tab_label | escape }}){%- endif -%} {%- else -%} {{- source -}} {%- endif -%}
{%- endfor -%}
{%- if rotator -%} {%- endif -%}
{% stylesheet %} .lib-press { 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-press__inner { max-width: 1200px; margin: 0 auto; } .lib-press--full .lib-press__inner { max-width: none; } @media (max-width: 749px) { .lib-press { padding-top: var(--lib-pt-m); padding-bottom: var(--lib-pb-m); } .lib-press[data-show='desktop'] { display: none; } } @media (min-width: 750px) { .lib-press[data-show='mobile'] { display: none; } } .lib-press__heading { margin: 0 0 clamp(1.5rem, 3.5vw, 2.5rem); font-size: clamp(1.5rem, 2.6vw, 2.125rem); line-height: 1.15; letter-spacing: -0.02em; } .lib-press__heading--small { font-size: 0.875rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.75; } .lib-press__heading--large { font-size: clamp(2rem, 4vw, 3rem); } /* Grid: one card per quote. */ .lib-press__quotes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); gap: clamp(1rem, 2.5vw, 1.75rem); } .lib-press__quote { display: flex; flex-direction: column; justify-content: space-between; gap: 1.25rem; margin: 0; padding: clamp(1.25rem, 2.5vw, 1.75rem); border-radius: 14px; background: var(--lib-card); } .lib-press__text { margin: 0; font-size: clamp(1.0625rem, 1.5vw, 1.25rem); line-height: 1.45; text-wrap: pretty; } .lib-press__text--small { font-size: 1rem; } .lib-press__text--large { font-size: clamp(1.25rem, 2.2vw, 1.75rem); line-height: 1.35; letter-spacing: -0.01em; } .lib-press__text > p { display: inline; margin: 0; } .lib-press__mark { margin-right: 0.1em; color: var(--lib-accent); font-weight: 700; } .lib-press__source { display: flex; align-items: center; min-height: var(--lib-logo-h); } .lib-press__logo { display: block; width: auto; max-width: 10rem; height: var(--lib-logo-h); object-fit: contain; } .lib-press[data-mono] .lib-press__logo { filter: grayscale(1); opacity: 0.8; } .lib-press__name { font-family: Georgia, 'Times New Roman', serif; font-size: 1.0625rem; font-weight: 700; letter-spacing: 0.01em; } .lib-press__link { display: inline-flex; align-items: center; min-height: 2.75rem; color: inherit; text-decoration: none; } .lib-press__link:hover .lib-press__name { text-decoration: underline; text-underline-offset: 0.2em; } .lib-press__link:focus-visible { outline: 2px solid var(--lib-accent); outline-offset: 3px; border-radius: 4px; } .lib-press__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } /* Rotator: one large quote, the logos below switch it. */ .lib-press[data-ready] .lib-press__quotes { display: block; } .lib-press[data-ready] .lib-press__quote { align-items: center; max-width: 52rem; margin-inline: auto; padding: 0; background: none; text-align: center; } .lib-press[data-ready] .lib-press__quote[hidden] { display: none; } .lib-press[data-ready] .lib-press__text { font-size: clamp(1.375rem, 2.8vw, 2rem); line-height: 1.3; letter-spacing: -0.01em; } .lib-press[data-ready] .lib-press__source { display: none; } .lib-press__controls { display: flex; align-items: center; justify-content: center; gap: 0.75rem; margin-top: clamp(1.5rem, 4vw, 2.5rem); } .lib-press__controls[hidden] { display: none; } .lib-press__tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem clamp(0.75rem, 3vw, 2rem); } .lib-press__tab { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0.4rem 0.6rem; border: 0; border-bottom: 2px solid transparent; background: none; color: inherit; font: inherit; opacity: 0.72; cursor: pointer; transition: opacity 0.2s ease, border-color 0.2s ease; } .lib-press__tab:hover { opacity: 0.9; } .lib-press__tab[aria-selected='true'] { opacity: 1; border-bottom-color: var(--lib-accent); } .lib-press__tab:focus-visible, .lib-press__pause:focus-visible { outline: 2px solid var(--lib-accent); outline-offset: 2px; } .lib-press__pause { flex: none; display: grid; place-items: center; width: 2.75rem; height: 2.75rem; border: 1.5px solid color-mix(in srgb, var(--lib-text) 30%, transparent); border-radius: 50%; background: none; color: inherit; cursor: pointer; } .lib-press__pause .lib-press__icon-play, .lib-press__pause[data-paused] .lib-press__icon-pause { display: none; } .lib-press__pause[data-paused] .lib-press__icon-play { display: block; } .lib-press__inner[data-align='center'] .lib-press__heading { text-align: center; } .lib-press__inner[data-align='center'] .lib-press__quote { text-align: center; align-items: center; } @media (max-width: 749px) { .lib-press__inner[data-align-m='left'] .lib-press__heading { text-align: left; } .lib-press__inner[data-align-m='left'] .lib-press__quote { text-align: left; align-items: flex-start; } .lib-press__inner[data-align-m='center'] .lib-press__heading { text-align: center; } .lib-press__inner[data-align-m='center'] .lib-press__quote { text-align: center; align-items: center; } } @media (prefers-reduced-motion: no-preference) { .lib-press[data-animate][data-ready] .lib-press__quote:not([hidden]) { animation: lib-press-in 0.5s ease both; } } @media (prefers-reduced-motion: reduce) { .lib-press__tab { transition: none; } } @keyframes lib-press-in { from { opacity: 0; transform: translateY(6px); } } {% endstylesheet %} {% javascript %} (() => { if (customElements.get('lib-press-quotes')) return; const MS_PER_SECOND = 1000; class LibPressQuotes extends HTMLElement { connectedCallback() { const controls = this.querySelector('[data-controls]'); if (!controls) return; this.tabs = [...controls.querySelectorAll('[role="tab"]')]; this.panels = this.tabs.map((tab) => this.querySelector(`#${CSS.escape(tab.getAttribute('aria-controls'))}`)); this.panels.forEach((panel, i) => { panel.setAttribute('role', 'tabpanel'); panel.setAttribute('aria-labelledby', this.tabs[i].id); }); controls.hidden = false; this.toggleAttribute('data-ready', true); this.index = 0; this.show(0, false); controls.addEventListener('click', (event) => { const tab = event.target.closest('[role="tab"]'); if (tab) { this.stop(true); this.show(this.tabs.indexOf(tab), true); } }); controls.addEventListener('keydown', (event) => { const current = this.tabs.indexOf(document.activeElement); if (current < 0) return; const moves = {ArrowRight: current + 1, ArrowLeft: current - 1, Home: 0, End: this.tabs.length - 1}; if (!(event.key in moves)) return; event.preventDefault(); this.stop(true); this.show((moves[event.key] + this.tabs.length) % this.tabs.length, true); }); this.addEventListener('shopify:block:select', (event) => { const index = this.panels.findIndex((p) => p.id === `LibPress-${event.detail.blockId}`); if (index >= 0) { this.stop(true); this.show(index, false); } }); this.seconds = Number(this.dataset.autoplay) || 0; this.pauseButton = this.querySelector('[data-pause]'); const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (this.seconds > 0 && !reduced && this.pauseButton) { this.pauseButton.addEventListener('click', () => (this.paused ? this.start() : this.stop(true))); // Hovering or focusing the quotes holds the rotation (WCAG 2.2.2) without unpausing a manual pause. ['mouseenter', 'focusin'].forEach((type) => this.addEventListener(type, () => this.hold(true))); ['mouseleave', 'focusout'].forEach((type) => this.addEventListener(type, () => this.hold(false))); this.start(); } else { this.pauseButton?.remove(); } } disconnectedCallback() { clearInterval(this.timer); } show(index, focus) { this.index = index; this.tabs.forEach((tab, i) => { const active = i === index; tab.setAttribute('aria-selected', String(active)); tab.tabIndex = active ? 0 : -1; this.panels[i].hidden = !active; }); if (focus) this.tabs[index].focus(); } start() { this.paused = false; this.held = false; this.setPauseLabel(); clearInterval(this.timer); this.timer = setInterval(() => { if (!this.held) this.show((this.index + 1) % this.tabs.length, false); }, this.seconds * MS_PER_SECOND); } stop(byUser) { clearInterval(this.timer); if (byUser) this.paused = true; this.setPauseLabel(); } hold(value) { this.held = value; } setPauseLabel() { if (!this.pauseButton) return; const paused = Boolean(this.paused); this.pauseButton.toggleAttribute('data-paused', paused); this.pauseButton.setAttribute('aria-label', paused ? this.pauseButton.dataset.labelPlay : this.pauseButton.dataset.labelPause); } } customElements.define('lib-press-quotes', LibPressQuotes); })(); {% endjavascript %} {% schema %} { "name": "Lib · Press quotes", "tag": "section", "class": "lib-section", "max_blocks": 8, "settings": [ { "type": "paragraph", "content": "Use only coverage you actually received, and logos you have the right to show." }, { "type": "header", "content": "Content" }, { "type": "inline_richtext", "id": "heading", "label": "Heading", "default": "As seen in" }, { "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 (label)" }, { "value": "medium", "label": "Medium" }, { "value": "large", "label": "Large" } ], "default": "small" }, { "type": "text", "id": "new_tab_label", "label": "New tab notice (screen readers)", "default": "opens in a new tab" }, { "type": "header", "content": "Layout" }, { "type": "select", "id": "layout", "label": "Layout", "options": [ { "value": "grid", "label": "Quote cards" }, { "value": "rotator", "label": "One quote, logos switch it" } ], "default": "rotator" }, { "type": "range", "id": "autoplay_seconds", "label": "Rotate every (0 = off)", "info": "Rotator only. Shoppers get a pause button; never rotates when reduced motion is on.", "min": 0, "max": 12, "step": 1, "unit": "s", "default": 6 }, { "type": "text", "id": "tabs_label", "label": "Logo list name (screen readers)", "default": "Publications" }, { "type": "text", "id": "pause_label", "label": "Pause button label (screen readers)", "default": "Pause quotes" }, { "type": "text", "id": "play_label", "label": "Play button label (screen readers)", "default": "Play quotes" }, { "type": "select", "id": "quote_size", "label": "Quote size (cards)", "options": [ { "value": "small", "label": "Small" }, { "value": "medium", "label": "Medium" }, { "value": "large", "label": "Large" } ], "default": "medium" }, { "type": "checkbox", "id": "show_marks", "label": "Show quotation mark", "default": true }, { "type": "range", "id": "logo_height", "label": "Logo height", "min": 16, "max": 64, "step": 2, "unit": "px", "default": 28 }, { "type": "checkbox", "id": "mono_logos", "label": "Show logos in grayscale", "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": "Accent (quotation mark, selected logo)", "default": "#7A5A3A" }, { "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": 72 }, { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 72 }, { "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 between quotes", "info": "Never when reduced motion is on.", "default": true } ], "blocks": [ { "type": "quote", "name": "Quote", "settings": [ { "type": "richtext", "id": "quote", "label": "Quote", "default": "

A short line the publication wrote about you.

" }, { "type": "text", "id": "publication", "label": "Publication", "info": "Shown when there is no logo, and used as the logo's alt text.", "default": "Publication" }, { "type": "image_picker", "id": "logo", "label": "Logo" }, { "type": "url", "id": "link", "label": "Link to the article" }, { "type": "checkbox", "id": "new_tab", "label": "Open link in a new tab", "default": true } ] } ], "presets": [ { "name": "Lib · Press quotes", "blocks": [{ "type": "quote" }, { "type": "quote" }, { "type": "quote" }] } ] } {% endschema %}