Let’s build a fun testimonial with Astro, Tailwind CSS and Alpinejs!
Originally posted: https://lexingtonthemes.com/tutorials/how-to-create-an-interactive-testimonial-with-astro-tailwind-css-and-alpine-js/
Let’s use Astro to make a template so we don’t have to write the same code over and over. We’ll put our data in an array and send it to the Alpine.js component.
This array represents a single testimonial object within a larger collection of testimonials. Each object in the collection includes several key pieces of information about the testimonial:
id
: Unique identifier for each testimonial.
content
: The testimonial text.
imageUrl
: Link or path to an associated image.
name
: The name of the testimonial provider.
title
: Their professional title or role.
Here’s the code snippet for the testimonial object:
Copy{
id: 1,
content:
"Johnny is like a unicorn in a field of horses, magically bridging the gap between design and coding...",
imageUrl:
"https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MjN8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D",
name: "Jhonny Mnemonic",
title: "Chief Wizard of Nowhere Land",
},
Alpine.js facilitates the interactive elements within the testimonials section through:
State Management: x-data
initializes a component state, testimonialActive
, which tracks the currently active testimonial. This state is crucial for determining which testimonial content to display.
In this cse we are using the 1 testimonial
Copy<div x-data="{ testimonialActive: 1 }"></div>
Adjust the number in testimonialActive to set a different default testimonial.
2.3. Conditional Rendering: x-show directive dynamically shows or hides a testimonial based on whether its index matches the testimonialActive state.
Copy<div x-show={`testimonialActive === ${index + 1}`}>
Complete component for rendering testimonials dynamically:
Copy <!-- Dynamically render testimonials -->
{
testimonials.map((testimonial, index) => (
<div
class="items-center pb-6 mx-auto text-4xl italic font-medium text-center text-base-200 lg:h-64 serif text-balance "
x-show={`testimonialActive === ${index + 1}`}
style="display: none;">
<p>
<span class="text-[#a180ea]">"</span>
{testimonial.content}
<span class="text-[#a180ea]">"</span>
</p>
</div>
))
}
<!-- Dynamically render name and role -->
{
testimonials.map((testimonial, index) => (
<div
class="py-6 text-center"
x-show={`testimonialActive === ${index + 1}`}
style="display: none;">
<h2 class="text-base font-medium text-white ">{testimonial.name}</h2>
<a
href="#"
class="text-xs text-base-500">
{testimonial.title}
</a>
</div>
))
}
Event Handling: @click.prevent
to change the active testimonial based on the user’s selection..
Copy<button @click.prevent="{`testimonialActive" ="${index" + 1}`}></button>
For navigating between testimonials:
Copy<!--
Buttons to change the active testimonial
Dynamically render avatars
-->
{ testimonials.map((testimonial, index) => (
<button
@click.prevent="{`testimonialActive"
="${index"
+
1}`}
class="inline-block mx-2 font-bold text-center rounded-xl focus:outline-none focus:ring-2 ring-offset-2 ring-white ring-offset-[#141521] size-12"
>
<img
class="inline-block object-cover size-12 rounded-xl"
src="{testimonial.imageUrl}"
alt="#_"
/>
</button>
)) }
That was it, short, brief and straight to the point, don’t forget to grab the code and do something cool with it!
/Michael Andreuzza
Join Michael on Peerlist!
Join amazing folks like Michael and thousands of other people in tech.
Create ProfileJoin with Michael’s personal invite link.
0
19
0