Skip to content

Commit 960ac6d

Browse files
committed
Update mobile view.
1 parent d8b203f commit 960ac6d

File tree

1 file changed

+95
-24
lines changed

1 file changed

+95
-24
lines changed

src/components/sections/speakers.astro

Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ const featuredSpeakers = getRandomSpeakers(validSpeakers, 15);
1818
1919
const sectionTitle = "Featured Speakers";
2020
const sectionSubtitle = "Meet some of our amazing speakers";
21+
22+
// Helper function to truncate names if needed
23+
function formatSpeakerName(name: string) {
24+
// Option: You could truncate very long names
25+
// if (name.length > 20) {
26+
// return name.substring(0, 18) + '...';
27+
// }
28+
return name;
29+
}
2130
---
2231

2332
<section class="py-16 px-4 bg-gray-50">
@@ -43,10 +52,18 @@ const sectionSubtitle = "Meet some of our amazing speakers";
4352
loading="eager"
4453
/>
4554
</div>
46-
<div class="p-4 text-center">
47-
<h3 class="font-bold text-lg text-gray-900 group-hover:text-primary transition-colors">
48-
{speaker.data.name}
55+
<div class="p-4 text-center h-[88px] flex flex-col justify-center">
56+
<!-- Solution: Use text-ellipsis with 2 lines max and remove whitespace-nowrap -->
57+
<h3 class="font-bold text-lg text-gray-900 group-hover:text-primary transition-colors line-clamp-2">
58+
{formatSpeakerName(speaker.data.name)}
4959
</h3>
60+
61+
<!-- Optional: Add role/title with ellipsis if available -->
62+
{speaker.data.title && (
63+
<p class="text-sm text-gray-600 mt-1 line-clamp-1">
64+
{speaker.data.title}
65+
</p>
66+
)}
5067
</div>
5168
</div>
5269
</a>
@@ -70,30 +87,52 @@ const sectionSubtitle = "Meet some of our amazing speakers";
7087
document.addEventListener('DOMContentLoaded', () => {
7188
const track = document.querySelector('.speakers-track') as HTMLElement;
7289
const slides = document.querySelectorAll('.speaker-slide');
90+
const totalOriginalSlides = slides.length / 2;
7391

7492
if (!track || slides.length === 0) return;
7593

76-
const slideWidth = 100 / 5;
77-
const totalOriginalSlides = slides.length / 2;
7894
let currentPosition = 0;
7995
const scrollSpeed = 4000;
96+
let slidingInterval: ReturnType<typeof setInterval> | null = null;
97+
98+
// Function to determine slides per view based on window width
99+
function getSlidesPerView() {
100+
const width = window.innerWidth;
101+
if (width <= 480) return 1;
102+
if (width <= 640) return 2;
103+
if (width <= 768) return 3;
104+
if (width <= 1024) return 4;
105+
return 5;
106+
}
80107

81-
slides.forEach((slide) => {
82-
(slide as HTMLElement).style.flexBasis = `${slideWidth}%`;
83-
});
108+
function updateCarouselSettings() {
109+
const slidesPerView = getSlidesPerView();
110+
const slideWidth = 100 / slidesPerView;
84111

85-
startAnimation();
112+
// Reset position when breakpoint changes
113+
currentPosition = 0;
114+
track.style.transition = 'none';
115+
track.style.transform = `translateX(0)`;
86116

87-
function startAnimation() {
117+
// Clear and restart animation
118+
if (slidingInterval !== null) {
119+
clearInterval(slidingInterval);
120+
}
121+
startAnimation(slideWidth);
122+
}
123+
124+
function startAnimation(slideWidth: number) {
125+
// Initial setup
88126
moveCarousel();
89-
let slidingInterval = setInterval(moveCarousel, scrollSpeed);
127+
slidingInterval = setInterval(moveCarousel, scrollSpeed);
90128

91129
function moveCarousel() {
92130
currentPosition += slideWidth;
93131

94132
track.style.transition = 'transform 1000ms linear';
95133
track.style.transform = `translateX(-${currentPosition}%)`;
96134

135+
// Reset when we've scrolled through the original set of slides
97136
if (currentPosition >= slideWidth * totalOriginalSlides) {
98137
setTimeout(() => {
99138
track.style.transition = 'none';
@@ -103,27 +142,43 @@ const sectionSubtitle = "Meet some of our amazing speakers";
103142
setTimeout(() => {
104143
track.style.transition = 'transform 1000ms linear';
105144
}, 20);
106-
}, 4000);
145+
}, 1000);
107146
}
108147
}
148+
}
149+
150+
// Start the carousel
151+
updateCarouselSettings();
109152

110-
const carouselContainer = document.querySelector('.speakers-carousel-container');
111-
carouselContainer?.addEventListener('mouseenter', () => {
153+
// Update on window resize
154+
window.addEventListener('resize', () => {
155+
updateCarouselSettings();
156+
});
157+
158+
// Pause on hover
159+
const carouselContainer = document.querySelector('.speakers-carousel-container');
160+
carouselContainer?.addEventListener('mouseenter', () => {
161+
if (slidingInterval !== null) {
112162
clearInterval(slidingInterval);
113-
});
163+
slidingInterval = null;
164+
}
165+
});
114166

115-
carouselContainer?.addEventListener('mouseleave', () => {
116-
slidingInterval = setInterval(moveCarousel, scrollSpeed);
117-
});
167+
carouselContainer?.addEventListener('mouseleave', () => {
168+
updateCarouselSettings();
169+
});
118170

119-
document.addEventListener('visibilitychange', () => {
120-
if (document.hidden) {
171+
// Pause when tab is not visible
172+
document.addEventListener('visibilitychange', () => {
173+
if (document.hidden) {
174+
if (slidingInterval !== null) {
121175
clearInterval(slidingInterval);
122-
} else {
123-
slidingInterval = setInterval(moveCarousel, scrollSpeed);
176+
slidingInterval = null;
124177
}
125-
});
126-
}
178+
} else {
179+
updateCarouselSettings();
180+
}
181+
});
127182
});
128183
</script>
129184

@@ -137,6 +192,22 @@ const sectionSubtitle = "Meet some of our amazing speakers";
137192
will-change: transform;
138193
}
139194

195+
/* Line clamping for text overflow */
196+
.line-clamp-1 {
197+
display: -webkit-box;
198+
-webkit-line-clamp: 1;
199+
-webkit-box-orient: vertical;
200+
overflow: hidden;
201+
}
202+
203+
.line-clamp-2 {
204+
display: -webkit-box;
205+
-webkit-line-clamp: 2;
206+
-webkit-box-orient: vertical;
207+
overflow: hidden;
208+
}
209+
210+
/* These styles match the responsive classes used in the HTML */
140211
@media (max-width: 1024px) {
141212
.speaker-slide {
142213
width: 25%;

0 commit comments

Comments
 (0)