feat: add interactivity with alpinejs (#34)
* first stages of implementing alpinejs * add link to projects slideshow * begin adding nav bar * inpired hero from flaco theme * fix posts showcase fixed to publish current work to latest * revert docker action * update astro version
This commit is contained in:
parent
37f4fa17b8
commit
8df8272d6d
22 changed files with 379 additions and 320 deletions
97
src/components/Carousel.astro
Normal file
97
src/components/Carousel.astro
Normal file
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
interface Props {
|
||||
data: string;
|
||||
}
|
||||
|
||||
const { data } = Astro.props;
|
||||
---
|
||||
|
||||
<div
|
||||
class="pt-6"
|
||||
data-slides={data}
|
||||
x-data="{
|
||||
// Sets the time between each slides in milliseconds
|
||||
autoplayIntervalTime: 5000,
|
||||
init() {
|
||||
this.slides = JSON.parse(this.$el.dataset.slides);
|
||||
},
|
||||
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="relative w-full overflow-hidden"
|
||||
>
|
||||
<div class="relative min-h-[50svh] w-full">
|
||||
<template x-for="(slide, index) in slides">
|
||||
<div
|
||||
x-cloak
|
||||
x-show="currentSlideIndex == index + 1"
|
||||
class="absolute inset-0"
|
||||
x-transition.opacity.duration.1000ms
|
||||
>
|
||||
<img
|
||||
class="absolute inset-0 h-full w-full rounded-md object-cover"
|
||||
x-bind:src="slide.data.image.url.src"
|
||||
x-bind:alt="slide.data.image.alt"
|
||||
/>
|
||||
<a
|
||||
class="absolute inset-0 z-20"
|
||||
x-bind:aria-label="slide.data.title"
|
||||
x-bind:href="'/' + slide.collection + '/' + slide.slug"></a>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<template x-for="(slide, index) in slides">
|
||||
<div
|
||||
x-show="currentSlideIndex == index + 1"
|
||||
class="text-secondary flex justify-end pt-1 text-right font-serif text-lg"
|
||||
>
|
||||
<div class="flex w-full flex-col items-end">
|
||||
<h3
|
||||
x-text="slide.data.title"
|
||||
x-bind:aria-describedby="'slide' + (index + 1) + 'Description'"
|
||||
class="border-tertiary/30 w-fit border-t italic"
|
||||
>
|
||||
</h3>
|
||||
<p
|
||||
class="text-tertiary w-fit text-sm text-pretty lg:w-1/2"
|
||||
x-text="slide.data.description"
|
||||
x-bind:id="'slide' + (index + 1) + 'Description'"
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue