Skip to content
This repository was archived by the owner on Oct 15, 2025. It is now read-only.

Commit 5db8372

Browse files
authored
Sm screen testimonial carousel (#209)
* Update Enterprise.svelte * Sm screen testimonial carousel
1 parent 9411b90 commit 5db8372

File tree

1 file changed

+97
-8
lines changed

1 file changed

+97
-8
lines changed

src/lib/components/sections/Testimonials.svelte

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script lang="ts">
2+
import { fly } from 'svelte/transition';
23
const testimonials = [
34
45
{
@@ -46,21 +47,109 @@
4647
image: "",
4748
},
4849
];
50+
let currentSlide = 0;
51+
let isAnimating = false;
52+
function nextSlide() {
53+
if (isAnimating) return;
54+
isAnimating = true;
55+
currentSlide = (currentSlide + 1) % testimonials.length;
56+
setTimeout(() => { isAnimating = false; }, 300);
57+
}
58+
function prevSlide() {
59+
if (isAnimating) return;
60+
isAnimating = true;
61+
currentSlide = currentSlide === 0 ? testimonials.length - 1 : currentSlide - 1;
62+
setTimeout(() => { isAnimating = false; }, 300);
63+
}
64+
function goToSlide(index: number) {
65+
if (isAnimating) return;
66+
isAnimating = true;
67+
currentSlide = index;
68+
setTimeout(() => { isAnimating = false; }, 300);
69+
}
4970
</script>
5071

5172

5273
<section class="relative py-20 bg-background overflow-auto">
53-
<div class="container max-w-7xl mx-auto">
54-
<div class=" h-[400px] md:h-[800px] overflow-y-auto relative [&::-webkit-scrollbar]:w-2
55-
[&::-webkit-scrollbar-track]:rounded-full
56-
[&::-webkit-scrollbar-track]:bg-background
57-
[&::-webkit-scrollbar-thumb]:rounded-full
58-
[&::-webkit-scrollbar-thumb]:bg-muted">
74+
<div class="container max-w-7xl mx-auto">
75+
<!-- Mobile: Carousel -->
76+
<div class="md:hidden relative">
77+
<div class="h-[400px] relative overflow-hidden">
78+
{#each testimonials as testimonial, index}
79+
{#if index === currentSlide}
80+
<div
81+
class="absolute inset-0 w-full"
82+
transition:fly={{ x: 300, duration: 300 }}
83+
>
84+
<div class="w-full max-w-sm mx-auto bg-background border rounded-lg p-6 h-full flex flex-col">
85+
<p class="text-foreground mb-4 text-left whitespace-pre-line flex-grow">{testimonial.text}</p>
86+
<div class="flex items-center gap-3 pt-4 border-t mt-4 flex-none">
87+
{#if testimonial.image}
88+
<div class="w-12 h-12 rounded-full overflow-hidden bottom-0 flex-shrink-0">
89+
<img
90+
src={testimonial.image}
91+
alt={testimonial.author}
92+
class="w-full h-full object-cover"
93+
/>
94+
</div>
95+
{:else}
96+
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0">
97+
<span class="text-xl font-bold text-primary">
98+
{testimonial.author[0]}
99+
</span>
100+
</div>
101+
{/if}
102+
<div class="text-left">
103+
<div class="font-semibold text-foreground">{testimonial.author}</div>
104+
<div class="text-xs text-muted-foreground">{testimonial.role} {testimonial.company}</div>
105+
</div>
106+
</div>
107+
</div>
108+
</div>
109+
{/if}
110+
{/each}
111+
</div>
112+
113+
<!-- Navigation Buttons -->
114+
<button
115+
class="absolute left-2 top-1/2 transform -translate-y-1/2 bg-background/80 hover:bg-background border rounded-full p-2 shadow-lg transition-all"
116+
on:click={prevSlide}
117+
aria-label="Previous testimonial"
118+
>
119+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
120+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
121+
</svg>
122+
</button>
123+
124+
<button
125+
class="absolute right-2 top-1/2 transform -translate-y-1/2 bg-background/80 hover:bg-background border rounded-full p-2 shadow-lg transition-all"
126+
on:click={nextSlide}
127+
aria-label="Next testimonial"
128+
>
129+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
130+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
131+
</svg>
132+
</button>
133+
134+
<!-- Slide Indicators -->
135+
<div class="flex justify-center gap-2 mt-4">
136+
{#each testimonials as _, index}
137+
<button
138+
class="w-2 h-2 rounded-full transition-all {index === currentSlide ? 'bg-primary' : 'bg-muted'}"
139+
on:click={() => goToSlide(index)}
140+
aria-label="Go to slide {index + 1}"
141+
></button>
142+
{/each}
143+
</div>
144+
</div>
145+
146+
<!-- Desktop: Masonry Layout -->
147+
<div class="hidden md:block h-[800px] overflow-y-auto relative [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:rounded-full [&::-webkit-scrollbar-track]:bg-background [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-muted">
59148

60149
<div class="columns-1 md:columns-2 lg:columns-3 gap-6">
61150
{#each testimonials as testimonial}
62-
<div class="mb-6 break-inside-avoid bg-background border rounded-lg p-6">
63-
<p class="text-foreground mb-4 text-left whitespace-pre-line">{testimonial.text}</p>
151+
<div class="mb-6 break-inside-avoid bg-background border rounded-lg p-6 flex flex-col h-full">
152+
<p class="text-foreground mb-4 text-left whitespace-pre-line flex-grow">{testimonial.text}</p>
64153
<div class="flex items-center gap-3 pt-4 border-t mt-4 flex-none">
65154
{#if testimonial.image}
66155
<div class="w-12 h-12 rounded-full overflow-hidden flex-shrink-0">

0 commit comments

Comments
 (0)