<div x-data="{
// Sets the time between each slides in milliseconds
autoplayIntervalTime: ,
slides: [
{
imgSrc: 'https://penguinui.s3.amazonaws.com/component-assets/carousel/default-slide-1.webp',
imgAlt: 'Vibrant abstract painting with swirling blue and light pink hues on a canvas.',
title: 'Front end developers',
description: 'The architects of the digital world, constantly battling against their mortal enemy – browser compatibility.',
},
{
imgSrc: 'https://penguinui.s3.amazonaws.com/component-assets/carousel/default-slide-2.webp',
imgAlt: 'Vibrant abstract painting with swirling red, yellow, and pink hues on a canvas.',
title: 'Back end developers',
description: 'Because not all superheroes wear capes, some wear headphones and stare at terminal screens',
},
{
imgSrc: 'https://penguinui.s3.amazonaws.com/component-assets/carousel/default-slide-3.webp',
imgAlt: 'Vibrant abstract painting with swirling blue and purple hues on a canvas.',
title: 'Full stack developers',
description: 'Where "burnout" is just a fancy term for "Tuesday".',
},
],
currentSlideIndex: 1,
isPaused: false,
autoplayInterval: null,
previous() {
if (this.currentSlideIndex > 1) {
this.currentSlideIndex = this.currentSlideIndex - 1
} else {
// If it's the first slide, go to the last slide
this.currentSlideIndex = this.slides.length
}
},
next() {
if (this.currentSlideIndex < this.slides.length) {
this.currentSlideIndex = this.currentSlideIndex + 1
} else {
// If it's the last slide, go to the first slide
this.currentSlideIndex = 1
}
},
autoplay() {
this.autoplayInterval = setInterval(() => {
if (! this.isPaused) {
this.next()
}
}, this.autoplayIntervalTime)
},
// Updates interval time
setAutoplayInterval(newIntervalTime) {
clearInterval(this.autoplayInterval)
this.autoplayIntervalTime = newIntervalTime
this.autoplay()
},
}" x-init="autoplay" class="">
<!-- slides -->
<!-- Change min-h-[50svh] to your preferred height size -->
<div class="">
<template x-for="(slide, index) in slides">
<div x-cloak x-show="currentSlideIndex == index + 1" class="" x-transition.opacity.duration.1000ms>
<!-- Title and description -->
<div class="">
<h3 class="" x-text="slide.title" x-bind:aria-describedby="'slide' + (index + 1) + 'Description'"></h3>
<p class="" x-text="slide.description" x-bind:id="'slide' + (index + 1) + 'Description'"></p>
</div>
<img class="" x-bind:src="slide.imgSrc" x-bind:alt="slide.imgAlt" />
</div>
</template>
</div>
<!-- Pause/Play Button -->
<button type="button" class="" aria-label="pause carousel" x-on:click="(isPaused = !isPaused), setAutoplayInterval(autoplayIntervalTime)" x-bind:aria-pressed="isPaused">
<svg x-cloak x-show="isPaused" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="">
<path fill-rule="evenodd" d="M2 10a8 8 0 1 1 16 0 8 8 0 0 1-16 0Zm6.39-2.908a.75.75 0 0 1 .766.027l3.5 2.25a.75.75 0 0 1 0 1.262l-3.5 2.25A.75.75 0 0 1 8 12.25v-4.5a.75.75 0 0 1 .39-.658Z" clip-rule="evenodd">
</svg>
<svg x-cloak x-show="!isPaused" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="">
<path fill-rule="evenodd" d="M2 10a8 8 0 1 1 16 0 8 8 0 0 1-16 0Zm5-2.25A.75.75 0 0 1 7.75 7h.5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1-.75-.75v-4.5Zm4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1-.75-.75v-4.5Z" clip-rule="evenodd">
</svg>
</button>
<!-- indicators -->
<div class="" role="group" aria-label="slides" >
<template x-for="(slide, index) in slides">
<button class="" x-on:click="(currentSlideIndex = index + 1), setAutoplayInterval(autoplayIntervalTime)" x-bind:class="[currentSlideIndex === index + 1 ? 'bg-' : 'bg-/50']" x-bind:aria-label="'slide ' + (index + 1)"></button>
</template>
</div>
</div>
<div x-data="carousel({
// Sets the time between each slides in milliseconds
intervalTime: ,
slides: [
{
imgSrc: 'https://penguinui.s3.amazonaws.com/component-assets/carousel/default-slide-1.webp',
imgAlt: 'Vibrant abstract painting with swirling blue and light pink hues on a canvas.',
title: 'Front end developers',
description: 'The architects of the digital world, constantly battling against their mortal enemy – browser compatibility.',
},
{
imgSrc: 'https://penguinui.s3.amazonaws.com/component-assets/carousel/default-slide-2.webp',
imgAlt: 'Vibrant abstract painting with swirling red, yellow, and pink hues on a canvas.',
title: 'Back end developers',
description: 'Because not all superheroes wear capes, some wear headphones and stare at terminal screens',
},
{
imgSrc: 'https://penguinui.s3.amazonaws.com/component-assets/carousel/default-slide-3.webp',
imgAlt: 'Vibrant abstract painting with swirling blue and purple hues on a canvas.',
title: 'Full stack developers',
description: 'Where "burnout" is just a fancy term for "Tuesday".',
},
],
})" x-init="autoplay" class="">
<!-- slides -->
<!-- Change min-h-[50svh] to your preferred height size -->
<div class="">
<template x-for="(slide, index) in slides">
<div x-cloak x-show="currentSlideIndex == index + 1" class="" x-transition.opacity.duration.1000ms>
<!-- Title and description -->
<div class="">
<h3 class="" x-text="slide.title" x-bind:aria-describedby="'slide' + (index + 1) + 'Description'"></h3>
<p class="" x-text="slide.description" x-bind:id="'slide' + (index + 1) + 'Description'"></p>
</div>
<img class="" x-bind:src="slide.imgSrc" x-bind:alt="slide.imgAlt" />
</div>
</template>
</div>
<!-- Pause/Play Button -->
<button type="button" class="" aria-label="pause carousel" x-on:click="(isPaused = !isPaused), setAutoplayIntervalTime(autoplayIntervalTime)" x-bind:aria-pressed="isPaused">
<svg x-cloak x-show="isPaused" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="">
<path fill-rule="evenodd" d="M2 10a8 8 0 1 1 16 0 8 8 0 0 1-16 0Zm6.39-2.908a.75.75 0 0 1 .766.027l3.5 2.25a.75.75 0 0 1 0 1.262l-3.5 2.25A.75.75 0 0 1 8 12.25v-4.5a.75.75 0 0 1 .39-.658Z" clip-rule="evenodd">
</svg>
<svg x-cloak x-show="!isPaused" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="">
<path fill-rule="evenodd" d="M2 10a8 8 0 1 1 16 0 8 8 0 0 1-16 0Zm5-2.25A.75.75 0 0 1 7.75 7h.5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1-.75-.75v-4.5Zm4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1-.75-.75v-4.5Z" clip-rule="evenodd">
</svg>
</button>
<!-- indicators -->
<div class="" role="group" aria-label="slides" >
<template x-for="(slide, index) in slides">
<button class="" x-on:click="(currentSlideIndex = index + 1), setAutoplayIntervalTime(autoplayIntervalTime)" x-bind:class="[currentSlideIndex === index + 1 ? 'bg-' : 'bg-/50']" x-bind:aria-label="'slide ' + (index + 1)"></button>
</template>
</div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('carousel', (carouselData = {
slides: [],
intervalTime: 0,
},) => ({
slides: carouselData.slides,
autoplayIntervalTime: carouselData.intervalTime,
currentSlideIndex: 1,
isPaused: false,
autoplayInterval: null,
previous() {
if (this.currentSlideIndex > 1) {
this.currentSlideIndex = this.currentSlideIndex - 1
} else {
// If it's the first slide, go to the last slide
this.currentSlideIndex = this.slides.length
}
},
next() {
if (this.currentSlideIndex < this.slides.length) {
this.currentSlideIndex = this.currentSlideIndex + 1
} else {
// If it's the last slide, go to the first slide
this.currentSlideIndex = 1
}
},
autoplay() {
this.autoplayInterval = setInterval(() => {
if (! this.isPaused) {
this.next()
}
}, this.autoplayIntervalTime)
},
// Updates interval time
setAutoplayIntervalTime(newIntervalTime) {
clearInterval(this.autoplayInterval)
this.autoplayIntervalTime = newIntervalTime
this.autoplay()
},
}))
})
</script>