11"use client" ;
22
3- import { motion } from "framer-motion " ;
4- import { Terminal } from "lucide- react" ;
3+ import { Play , Terminal } from "lucide-react " ;
4+ import { motion } from "motion/ react" ;
55import Image from "next/image" ;
66import { Suspense } from "react" ;
77import { Tweet , TweetSkeleton , type TwitterComponents } from "react-tweet" ;
88
9+ const YOUTUBE_VIDEOS = [
10+ {
11+ id : "VIDEO_001" ,
12+ embedId : "g-ynSAdL6Ak" ,
13+ title : "This tool cured my JavaScript fatigue" ,
14+ } ,
15+ {
16+ id : "VIDEO_002" ,
17+ embedId : "uHUgw-Hi8HE" ,
18+ title : "I tried React again after 2 years of Svelte" ,
19+ } ,
20+ ] ;
21+
922const TWEET_IDS = [
1023 "1930194170418999437" ,
1124 "1907728148294447538" ,
@@ -114,6 +127,45 @@ export default function Testimonials() {
114127 } ,
115128 } ;
116129
130+ const VideoCard = ( {
131+ video,
132+ index,
133+ } : {
134+ video : ( typeof YOUTUBE_VIDEOS ) [ 0 ] ;
135+ index : number ;
136+ } ) => (
137+ < motion . div
138+ className = "w-full min-w-0"
139+ initial = { { opacity : 0 , y : 20 , scale : 0.95 } }
140+ animate = { { opacity : 1 , y : 0 , scale : 1 } }
141+ transition = { {
142+ delay : index * 0.1 ,
143+ duration : 0.4 ,
144+ ease : "easeOut" ,
145+ } }
146+ >
147+ < div className = "w-full min-w-0 overflow-hidden rounded border border-border" >
148+ < div className = "sticky top-0 z-10 border-border border-b px-3 py-2" >
149+ < div className = "flex items-center gap-2" >
150+ < Play className = "h-3 w-3 text-primary" />
151+ < span className = "font-semibold text-xs" > [{ video . id } ]</ span >
152+ </ div >
153+ </ div >
154+ < div className = "w-full min-w-0 overflow-hidden" >
155+ < div className = "relative aspect-video w-full" >
156+ < iframe
157+ src = { `https://www.youtube.com/embed/${ video . embedId } ` }
158+ title = { video . title }
159+ allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
160+ allowFullScreen
161+ className = "absolute inset-0 h-full w-full"
162+ />
163+ </ div >
164+ </ div >
165+ </ div >
166+ </ motion . div >
167+ ) ;
168+
117169 const TweetCard = ( {
118170 tweetId,
119171 index,
@@ -135,7 +187,7 @@ export default function Testimonials() {
135187 < div className = "sticky top-0 z-10 border-border border-b px-3 py-2" >
136188 < div className = "flex items-center gap-2" >
137189 < span className = "text-primary text-xs" > ▶</ span >
138- < span className = " font-semibold text-xs" >
190+ < span className = "font-semibold text-xs" >
139191 [TWEET_{ String ( index + 1 ) . padStart ( 3 , "0" ) } ]
140192 </ span >
141193 </ div >
@@ -153,6 +205,47 @@ export default function Testimonials() {
153205
154206 return (
155207 < div className = "mb-12 w-full max-w-full overflow-hidden px-4" >
208+ < div className = "mb-8" >
209+ < div className = "mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap" >
210+ < div className = "flex items-center gap-2" >
211+ < Play className = "h-5 w-5 text-primary" />
212+ < span className = "font-bold text-lg sm:text-xl" >
213+ VIDEO_TESTIMONIALS.LOG
214+ </ span >
215+ </ div >
216+ < div className = "hidden h-px flex-1 bg-border sm:block" />
217+ < span className = "w-full text-right text-muted-foreground text-xs sm:w-auto sm:text-left" >
218+ [{ YOUTUBE_VIDEOS . length } ENTRIES]
219+ </ span >
220+ </ div >
221+
222+ < div className = "block sm:hidden" >
223+ < motion . div
224+ className = "flex flex-col gap-4"
225+ variants = { containerVariants }
226+ initial = "hidden"
227+ animate = "visible"
228+ >
229+ { YOUTUBE_VIDEOS . map ( ( video , index ) => (
230+ < VideoCard key = { video . id } video = { video } index = { index } />
231+ ) ) }
232+ </ motion . div >
233+ </ div >
234+
235+ < div className = "hidden sm:block" >
236+ < motion . div
237+ className = "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3"
238+ variants = { containerVariants }
239+ initial = "hidden"
240+ animate = "visible"
241+ >
242+ { YOUTUBE_VIDEOS . map ( ( video , index ) => (
243+ < VideoCard key = { video . id } video = { video } index = { index } />
244+ ) ) }
245+ </ motion . div >
246+ </ div >
247+ </ div >
248+
156249 < div className = "mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap" >
157250 < div className = "flex items-center gap-2" >
158251 < Terminal className = "h-5 w-5 text-primary" />
0 commit comments