Skip to content

Commit c030519

Browse files
fix(web): add toggle functionality for displaying tweet testimonials (#590)
Co-authored-by: Aman Varshney <amanvarshney.work@gmail.com>
1 parent 45be22c commit c030519

File tree

2 files changed

+160
-64
lines changed

2 files changed

+160
-64
lines changed

apps/web/src/app/(home)/_components/sponsors-section.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ export default function SponsorsSection({
268268
<button
269269
type="button"
270270
onClick={() => setShowPastSponsors(!showPastSponsors)}
271-
className="flex w-full items-center gap-2 rounded p-2 text-left transition-colors hover:bg-muted/50"
271+
className="flex w-full items-center gap-2 rounded border border-muted p-2 text-left transition-colors hover:bg-muted"
272272
>
273273
{showPastSponsors ? (
274274
<ChevronUp className="h-4 w-4 text-muted-foreground" />

apps/web/src/app/(home)/_components/testimonials.tsx

Lines changed: 159 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"use client";
22

3-
import { Play, Terminal } from "lucide-react";
3+
import { ChevronDown, ChevronUp, Play, Terminal } from "lucide-react";
44
import { motion } from "motion/react";
55
import Image from "next/image";
6+
import { useState } from "react";
67
import { Tweet, type TwitterComponents } from "react-tweet";
78

89
export const components: TwitterComponents = {
@@ -104,6 +105,7 @@ export default function Testimonials({
104105
tweets: Array<{ tweetId: string }>;
105106
}) {
106107
const videosReversed = [...videos].reverse();
108+
const [showAllTweets, setShowAllTweets] = useState(false);
107109

108110
const getResponsiveColumns = (numCols: number) => {
109111
const columns: string[][] = Array(numCols)
@@ -197,77 +199,171 @@ export default function Testimonials({
197199
[{tweets.length} ENTRIES]
198200
</span>
199201
</div>
202+
200203
<div className="block sm:hidden">
201-
<motion.div
202-
className="flex flex-col gap-4"
203-
variants={containerVariants}
204-
initial="hidden"
205-
animate="visible"
206-
>
207-
{tweets.map((tweet, index) => (
208-
<TweetCard
209-
key={tweet.tweetId}
210-
tweetId={tweet.tweetId}
211-
index={index}
212-
/>
213-
))}
214-
</motion.div>
204+
<div className="relative">
205+
<motion.div
206+
className={`flex flex-col gap-4 overflow-hidden transition-all duration-500 ease-in-out ${showAllTweets ? "h-auto" : "h-[500px]"
207+
}`}
208+
variants={containerVariants}
209+
initial="hidden"
210+
animate="visible"
211+
>
212+
{tweets.map((tweet, index) => (
213+
<TweetCard
214+
key={tweet.tweetId}
215+
tweetId={tweet.tweetId}
216+
index={index}
217+
/>
218+
))}
219+
</motion.div>
220+
221+
{!showAllTweets && (
222+
<div className="pointer-events-none absolute right-0 bottom-10 left-0 h-32 bg-gradient-to-t from-muted/20 via-muted/40 to-transparent" />
223+
)}
224+
225+
<div className="my-4">
226+
<button
227+
type="button"
228+
onClick={() => setShowAllTweets(!showAllTweets)}
229+
className="flex w-full items-center gap-2 rounded border border-muted p-2 text-left transition-colors hover:bg-muted"
230+
>
231+
{showAllTweets ? (
232+
<ChevronUp className="h-4 w-4 text-muted-foreground" />
233+
) : (
234+
<ChevronDown className="h-4 w-4 text-muted-foreground" />
235+
)}
236+
<span className="font-semibold text-muted-foreground text-sm">
237+
TWEET_TESTIMONIALS.ARCHIVE
238+
</span>
239+
<span className="text-muted-foreground text-xs">
240+
({tweets.length})
241+
</span>
242+
<div className="mx-2 h-px flex-1 bg-border" />
243+
<span className="text-muted-foreground text-xs">
244+
{showAllTweets ? "HIDE" : "SHOW"}
245+
</span>
246+
</button>
247+
</div>
248+
</div>
215249
</div>
216250

217251
<div className="hidden sm:block lg:hidden">
218-
<motion.div
219-
className="grid grid-cols-2 gap-4"
220-
variants={containerVariants}
221-
initial="hidden"
222-
animate="visible"
223-
>
224-
{getResponsiveColumns(2).map((column, colIndex) => (
225-
<motion.div
226-
key={`col-2-${column.length > 0 ? column[0] : `empty-${colIndex}`}`}
227-
className="flex min-w-0 flex-col gap-4"
228-
variants={columnVariants}
252+
<div className="relative">
253+
<motion.div
254+
className={`grid grid-cols-2 gap-4 overflow-hidden transition-all duration-500 ease-in-out ${showAllTweets ? "h-auto" : "h-[450px]"
255+
}`}
256+
variants={containerVariants}
257+
initial="hidden"
258+
animate="visible"
259+
>
260+
{getResponsiveColumns(2).map((column, colIndex) => (
261+
<motion.div
262+
key={`col-2-${column.length > 0 ? column[0] : `empty-${colIndex}`}`}
263+
className="flex min-w-0 flex-col gap-4"
264+
variants={columnVariants}
265+
>
266+
{column.map((tweetId, tweetIndex) => {
267+
const globalIndex = colIndex + tweetIndex * 2;
268+
return (
269+
<TweetCard
270+
key={tweetId}
271+
tweetId={tweetId}
272+
index={globalIndex}
273+
/>
274+
);
275+
})}
276+
</motion.div>
277+
))}
278+
</motion.div>
279+
280+
{!showAllTweets && (
281+
<div className="pointer-events-none absolute right-0 bottom-10 left-0 h-32 bg-gradient-to-t from-muted/20 via-muted/40 to-transparent" />
282+
)}
283+
284+
<div className="my-4">
285+
<button
286+
type="button"
287+
onClick={() => setShowAllTweets(!showAllTweets)}
288+
className="flex w-full items-center gap-2 rounded border border-muted p-2 text-left transition-colors hover:bg-muted"
229289
>
230-
{column.map((tweetId, tweetIndex) => {
231-
const globalIndex = colIndex + tweetIndex * 2;
232-
return (
233-
<TweetCard
234-
key={tweetId}
235-
tweetId={tweetId}
236-
index={globalIndex}
237-
/>
238-
);
239-
})}
240-
</motion.div>
241-
))}
242-
</motion.div>
290+
{showAllTweets ? (
291+
<ChevronUp className="h-4 w-4 text-muted-foreground" />
292+
) : (
293+
<ChevronDown className="h-4 w-4 text-muted-foreground" />
294+
)}
295+
<span className="font-semibold text-muted-foreground text-sm">
296+
TWEET_TESTIMONIALS.ARCHIVE
297+
</span>
298+
<span className="text-muted-foreground text-xs">
299+
({tweets.length})
300+
</span>
301+
<div className="mx-2 h-px flex-1 bg-border" />
302+
<span className="text-muted-foreground text-xs">
303+
{showAllTweets ? "HIDE" : "SHOW"}
304+
</span>
305+
</button>
306+
</div>
307+
</div>
243308
</div>
244309

245310
<div className="hidden lg:block">
246-
<motion.div
247-
className="grid grid-cols-3 gap-4"
248-
variants={containerVariants}
249-
initial="hidden"
250-
animate="visible"
251-
>
252-
{getResponsiveColumns(3).map((column, colIndex) => (
253-
<motion.div
254-
key={`col-3-${column.length > 0 ? column[0] : `empty-${colIndex}`}`}
255-
className="flex min-w-0 flex-col gap-4"
256-
variants={columnVariants}
311+
<div className="relative">
312+
<motion.div
313+
className={`grid grid-cols-3 gap-4 overflow-hidden transition-all duration-500 ease-in-out ${showAllTweets ? "h-auto" : "h-[400px]"
314+
}`}
315+
variants={containerVariants}
316+
initial="hidden"
317+
animate="visible"
318+
>
319+
{getResponsiveColumns(3).map((column, colIndex) => (
320+
<motion.div
321+
key={`col-3-${column.length > 0 ? column[0] : `empty-${colIndex}`}`}
322+
className="flex min-w-0 flex-col gap-4"
323+
variants={columnVariants}
324+
>
325+
{column.map((tweetId, tweetIndex) => {
326+
const globalIndex = colIndex + tweetIndex * 3;
327+
return (
328+
<TweetCard
329+
key={tweetId}
330+
tweetId={tweetId}
331+
index={globalIndex}
332+
/>
333+
);
334+
})}
335+
</motion.div>
336+
))}
337+
</motion.div>
338+
339+
{!showAllTweets && (
340+
<div className="pointer-events-none absolute right-0 bottom-10 left-0 h-32 bg-gradient-to-t from-muted/20 via-muted/40 to-transparent" />
341+
)}
342+
343+
<div className="my-4">
344+
<button
345+
type="button"
346+
onClick={() => setShowAllTweets(!showAllTweets)}
347+
className="flex w-full items-center gap-2 rounded border border-muted p-2 text-left transition-colors hover:bg-muted"
257348
>
258-
{column.map((tweetId, tweetIndex) => {
259-
const globalIndex = colIndex + tweetIndex * 3;
260-
return (
261-
<TweetCard
262-
key={tweetId}
263-
tweetId={tweetId}
264-
index={globalIndex}
265-
/>
266-
);
267-
})}
268-
</motion.div>
269-
))}
270-
</motion.div>
349+
{showAllTweets ? (
350+
<ChevronUp className="h-4 w-4 text-muted-foreground" />
351+
) : (
352+
<ChevronDown className="h-4 w-4 text-muted-foreground" />
353+
)}
354+
<span className="font-semibold text-muted-foreground text-sm">
355+
TWEET_TESTIMONIALS.ARCHIVE
356+
</span>
357+
<span className="text-muted-foreground text-xs">
358+
({tweets.length})
359+
</span>
360+
<div className="mx-2 h-px flex-1 bg-border" />
361+
<span className="text-muted-foreground text-xs">
362+
{showAllTweets ? "HIDE" : "SHOW"}
363+
</span>
364+
</button>
365+
</div>
366+
</div>
271367
</div>
272368
</div>
273369
);

0 commit comments

Comments
 (0)