@@ -10,6 +10,8 @@ pub struct Example {
1010
1111#[ component]
1212pub fn GalleryExamples ( ) -> impl IntoView {
13+ let ( preview_image, set_preview_image) = signal :: < Option < String > > ( None ) ;
14+
1315 let examples = vec ! [
1416 Example {
1517 name: "3D Picking" ,
@@ -87,31 +89,78 @@ pub fn GalleryExamples() -> impl IntoView {
8789
8890 <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8" >
8991 { examples. into_iter( ) . map( |example| {
92+ let screenshot = example. screenshot. to_string( ) ;
93+ let screenshot_for_preview = screenshot. clone( ) ;
9094 view! {
91- <a
92- href=example. path
93- target="_blank"
94- rel="noopener noreferrer"
95- class="block bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden hover:shadow-xl transition-all hover:scale-105 cursor-pointer flex flex-col"
96- >
97- <img
98- src=example. screenshot
99- alt=example. name
100- class="w-full h-48 object-cover"
101- />
102- <div class="p-6 flex-1" >
95+ <div class="block bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden hover:shadow-xl transition-all hover:scale-105 flex flex-col" >
96+ <div class="relative" >
97+ <a
98+ href=example. path
99+ target="_blank"
100+ rel="noopener noreferrer"
101+ >
102+ <img
103+ src=example. screenshot
104+ alt=example. name
105+ class="w-full h-48 object-contain bg-gray-100 dark:bg-gray-700"
106+ />
107+ </a>
108+ <button
109+ on: click=move |e| {
110+ e. prevent_default( ) ;
111+ e. stop_propagation( ) ;
112+ set_preview_image. set( Some ( screenshot_for_preview. clone( ) ) ) ;
113+ }
114+ class="absolute top-2 right-2 p-2 bg-white dark:bg-gray-700 rounded-full shadow-lg hover:bg-gray-100 dark:hover:bg-gray-600 transition-colors"
115+ title="View full size"
116+ >
117+ <svg class="w-5 h-5 text-gray-700 dark:text-gray-200" fill="none" stroke="currentColor" viewBox="0 0 24 24" >
118+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" />
119+ </svg>
120+ </button>
121+ </div>
122+ <a
123+ href=example. path
124+ target="_blank"
125+ rel="noopener noreferrer"
126+ class="p-6 flex-1 cursor-pointer"
127+ >
103128 <h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-3" >
104129 { example. name}
105130 </h3>
106131 <p class="text-gray-600 dark:text-gray-300" >
107132 { example. description}
108133 </p>
109- </div >
110- </a >
134+ </a >
135+ </div >
111136 }
112137 } ) . collect_view( ) }
113138 </div>
114139 </div>
140+
141+ <Show when=move || preview_image. get( ) . is_some( ) >
142+ <div
143+ class="fixed inset-0 bg-black bg-opacity-75 z-50 flex items-center justify-center p-4"
144+ on: click=move |_| set_preview_image. set( None )
145+ >
146+ <div
147+ class="relative max-w-7xl max-h-full"
148+ on: click=move |e| e. stop_propagation( )
149+ >
150+ <button
151+ on: click=move |_| set_preview_image. set( None )
152+ class="absolute top-4 right-4 text-white hover:text-gray-300 text-4xl font-bold z-10 bg-black bg-opacity-50 rounded-full w-12 h-12 flex items-center justify-center leading-none"
153+ >
154+ "×"
155+ </button>
156+ <img
157+ src=move || preview_image. get( ) . unwrap_or_default( )
158+ class="max-w-full max-h-screen object-contain"
159+ alt="Preview"
160+ />
161+ </div>
162+ </div>
163+ </Show >
115164 </section>
116165 }
117166}
0 commit comments