<section class="lg:container adjusted-marg-y-md relative max-lg:mb-6" x-data="initSlider" x-init="if ($store.screen.isTablet) { calcPageSize(); $nextTick(function() { calcActive() }) }" @resize.window.debounce="if ($store.screen.isTablet) { calcPageSize(); $nextTick(() => calcActive()) }" role="group" aria-roledescription="Carousel" aria-label="Hero Product Slider">
<div :class="{
'relative w-full overflow-x-hidden': $store.screen.isTablet,
}">
<div :class="{
'relative flex flex-nowrap w-full overflow-auto js_slides snap': $store.screen.isTablet,
'grid grid-cols-2 gap-6': !$store.screen.isTablet
}" @scroll.debounce="$store.screen.isTablet && calcActive" aria-label="Slides">
<div :class="{
'js_slide flex-shrink-0 w-full': $store.screen.isTablet
}" aria-roledescription="slide" id="slide-0" aria-labelledby="tab-0" role="tabpanel" tabindex="0" :aria-label="'Slide ' + (1) + ' of ' + 2" :aria-hidden="active !== 0">
<div class="@container group h-full
">
<div class="relative h-full
flex items-center ">
<picture class="absolute inset-0 w-full h-full
">
<source srcset="/img/diagnostic/desktop-1.png" media="(min-width: 769px)" />
<img src="/img/diagnostic/mobile-1.png" alt="Analyser votre peau" class="object-cover w-full h-full " loading="lazy" />
</picture>
<div class="absolute inset-0
bg-black/04 mix-blend-overlay "></div>
<section class="relative flex items-center min-h-62 md:min-h-[346px] 2xl:min-h-88 3xl:min-h-100 adjusted-marg-y-sm
w-1/2 ">
<article class="
relative flex gap-3 w-full
flex-col adjusted-marg-l-sm border-l-8 border-naos ">
<div class="flex flex-col gap-1.5
">
<h2 class="h2 [&>span]:font-normal text-black">
Analyser votre peau
</h2>
<p class="h6-base [&>span]:md:font-semibold [&>span]:md:uppercase text-black">
Scannez votre peau et découvrez votre routine personalisée.
</p>
</div>
<div class="flex items-center gap-4">
<a href="#" type="button" class="w-max btn btn-dark btn-outline btn-size-lg">
Essayer le SkinObserver
</a>
</div>
</article>
</section>
</div>
</div>
</div>
<div :class="{
'js_slide flex-shrink-0 w-full': $store.screen.isTablet
}" aria-roledescription="slide" id="slide-1" aria-labelledby="tab-1" role="tabpanel" tabindex="0" :aria-label="'Slide ' + (2) + ' of ' + 2" :aria-hidden="active !== 1">
<div class="@container group h-full
">
<div class="relative h-full
flex items-center ">
<picture class="absolute inset-0 w-full h-full
">
<source srcset="/img/banner_cta/img_2.png" media="(min-width: 769px)" />
<img src="/img/banner_cta/img_2.png" alt="Banner Image" class="object-cover w-full h-full " loading="lazy" />
</picture>
<div class="absolute inset-0
bg-black/04 mix-blend-overlay "></div>
<section class="relative flex items-center min-h-62 md:min-h-[346px] 2xl:min-h-88 3xl:min-h-100 adjusted-marg-y-sm
adjusted-marg-x-sm
w-1/2 ">
<article class="
relative flex gap-3 w-full
flex-col ">
<div class="flex flex-col gap-1.5
">
<p class="h6-base [&>span]:md:font-semibold [&>span]:md:uppercase text-dark">
Skin Coach
</p>
<h2 class="h2 [&>span]:font-normal text-dark">
Des conseils personnalisés et gratuits
</h2>
<a href="#" class="
link-medium
link-dark
link-icon
font-bold items-center
">
<svg class=" shrink-0" width="20" height="20" stroke="currentColor" stroke-width="1.5" viewBox="0 0 21 20" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M10.5 5V10H14.25M18 10C18 14.1421 14.6421 17.5 10.5 17.5C6.35786 17.5 3 14.1421 3 10C3 5.85786 6.35786 2.5 10.5 2.5C14.6421 2.5 18 5.85786 18 10Z" stroke="currentColor" stroke-width="1.5" fill="none" />
</svg>
<span class="">30 min</span>
</a>
</div>
<div class="flex items-center gap-4">
<a href="#" type="button" class="w-max btn btn-dark btn-outline btn-size-lg">
Prendre rdv
</a>
</div>
</article>
</section>
</div>
</div>
</div>
</div>
</div>
<div class="block lg:hidden absolute bottom-0 w-full z-10">
<div class="md:container relative">
<div class="absolute left-1/2 transform -translate-x-1/2 h-full w-full flex justify-center items-center">
<div class="flex items-center ">
<div role="tablist" aria-label="Navigation du slider" class="flex flex-wrap justify-center gap-3">
<template x-for="(index, i) in Math.ceil(itemCount / pageSize)" :key="i">
<button class="shrink-0 block h-1 bg-black rounded-full shadow cursor-pointer transition-all duration-300 ease-in-out" role="tab" :id="'tab-' + (index-1)" :aria-controls="'slide-' + (index-1)" :aria-selected="Math.floor(active/pageSize) === index-1" :tabindex="Math.floor(active/pageSize) === index-1 ? 0 : -1" :class="{
'bg-opacity-100 w-22': Math.floor(active/pageSize) === index-1,
'bg-opacity-40 w-6': Math.floor(active/pageSize) !== index-1
}" @click="scrollTo((index-1)*pageSize);">
<span class="sr-only" x-text="'Aller au groupe de slides ' + index"></span>
</button>
</template>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
'use strict';
function initSlider() {
return {
active: 0,
itemCount: 0,
getSlider() {
return this.$root.querySelector('.js_slides');
},
pageSize: 4,
pageFillers: 0,
calcPageSize() {
const slider = this.getSlider();
if (slider) {
this.itemCount = slider.querySelectorAll('.js_slide').length;
this.pageSize = Math.round(slider.clientWidth / slider.querySelector('.js_slide').clientWidth);
this.pageFillers = (
this.pageSize * Math.ceil(this.itemCount / this.pageSize)
) - this.itemCount;
}
},
calcActive() {
const slider = this.getSlider();
if (slider) {
const sliderItems = this.itemCount + this.pageFillers;
const calculatedActiveSlide = slider.scrollLeft / (slider.scrollWidth / sliderItems);
this.active = Math.round(calculatedActiveSlide / this.pageSize) * this.pageSize;
}
},
scrollPrevious() {
this.scrollTo(this.active - this.pageSize);
},
scrollNext() {
this.scrollTo(this.active + this.pageSize);
},
scrollTo(idx) {
const slider = this.getSlider();
if (slider) {
const slideWidth = slider.scrollWidth / (this.itemCount + this.pageFillers);
slider.scrollLeft = Math.floor(slideWidth) * idx;
this.active = idx;
}
},
}
}
</script>
<section class="lg:container adjusted-marg-y-md relative max-lg:mb-6"
x-data="initSlider"
x-init="if ($store.screen.isTablet) { calcPageSize(); $nextTick(function() { calcActive() }) }"
@resize.window.debounce="if ($store.screen.isTablet) { calcPageSize(); $nextTick(() => calcActive()) }"
role="group"
aria-roledescription="Carousel"
aria-label="{{ title }}"
>
<div :class="{
'relative w-full overflow-x-hidden': $store.screen.isTablet,
}">
<div :class="{
'relative flex flex-nowrap w-full overflow-auto js_slides snap': $store.screen.isTablet,
'grid grid-cols-2 gap-6': !$store.screen.isTablet
}"
@scroll.debounce="$store.screen.isTablet && calcActive"
aria-label="Slides"
>
{% for item in items %}
{% set contentPosition = item.contentPosition|default('left') %}
<div
:class="{
'js_slide flex-shrink-0 w-full': $store.screen.isTablet
}"
aria-roledescription="slide"
id="slide-{{ loop.index0 }}"
aria-labelledby="tab-{{ loop.index0 }}"
role="tabpanel"
tabindex="0"
:aria-label="'Slide ' + ({{ loop.index }}) + ' of ' + {{ items|length }}"
:aria-hidden="active !== {{ loop.index0 }}"
>
{% if item.type is defined %}
{% render "@" ~ item.type %}
{% else %}
{% render "@card-product-full-width" with {
item: item,
contentPosition: contentPosition
} %}
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% if items|length > 1 %}
<div class="block lg:hidden absolute bottom-0 w-full z-10">
<div class="md:container relative">
{% if showPagination %}
<div class="absolute left-1/2 transform -translate-x-1/2 h-full w-full flex justify-center items-center">
{% render "@slider-pagination" %}
</div>
{% endif %}
{% if showNavigation %}
<div class="flex justify-end">
<div class="flex flex-row gap-4">
{% render "@template-button" with {
color: 'dark',
type: 'subtle',
icon_type: "only-icon",
size: 'sm',
border: true,
label: 'Voir le slide précédent',
icon: {
name: "heroicons--arrow-left-outline",
},
button_attribute: (":class=\"{ 'opacity-25 pointer-events-none' : active === 0 }\" @click=\"scrollPrevious\" :disabled=\"active === 0\"")|replace({'\"': '"'})
} %}
{% render "@template-button" with {
color: 'dark',
type: 'subtle',
icon_type: "only-icon",
size: 'sm',
border: true,
label: 'Voir le slide suivant',
icon: {
name: "heroicons--arrow-right-outline",
},
button_attribute: (":class=\"{ 'opacity-25 pointer-events-none' : active >= itemCount - pageSize }\" @click=\"scrollNext\" :disabled=\"active >= itemCount - pageSize\"")|replace({'\"': '"'})
} %}
</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
</section>
<script>
'use strict';
function initSlider() {
return {
active: 0,
itemCount: 0,
getSlider() {
return this.$root.querySelector('.js_slides');
},
pageSize: 4,
pageFillers: 0,
calcPageSize() {
const slider = this.getSlider();
if (slider) {
this.itemCount = slider.querySelectorAll('.js_slide').length;
this.pageSize = Math.round(slider.clientWidth / slider.querySelector('.js_slide').clientWidth);
this.pageFillers = (
this.pageSize * Math.ceil(this.itemCount / this.pageSize)
) - this.itemCount;
}
},
calcActive() {
const slider = this.getSlider();
if (slider) {
const sliderItems = this.itemCount + this.pageFillers;
const calculatedActiveSlide = slider.scrollLeft / (slider.scrollWidth / sliderItems);
this.active = Math.round(calculatedActiveSlide / this.pageSize) * this.pageSize;
}
},
scrollPrevious() {
this.scrollTo(this.active - this.pageSize);
},
scrollNext() {
this.scrollTo(this.active + this.pageSize);
},
scrollTo(idx) {
const slider = this.getSlider();
if (slider) {
const slideWidth = slider.scrollWidth / (this.itemCount + this.pageFillers);
slider.scrollLeft = Math.floor(slideWidth) * idx;
this.active = idx;
}
},
}
}
</script>
{
"title": "Hero Product Slider",
"maxVisibleSlides": 1,
"showNavigation": false,
"showPagination": true,
"items": [
{
"type": "banner--full-width-naos-border"
},
{
"type": "banner--skin-coatch"
}
]
}
No notes defined.