Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PixelPulse Gallery</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.2/dist/gsap.min.js"></script> | |
| <style> | |
| .gallery-item { | |
| transition: transform 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .gallery-item:hover { | |
| transform: scale(1.03); | |
| box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1); | |
| } | |
| .modal-overlay { | |
| background-color: rgba(0, 0, 0, 0.9); | |
| } | |
| .modal-image { | |
| max-height: 80vh; | |
| max-width: 90vw; | |
| } | |
| .nav-button { | |
| transition: all 0.3s ease; | |
| } | |
| .nav-button:hover { | |
| transform: scale(1.2); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen"> | |
| <!-- Navigation --> | |
| <nav class="bg-gray-200 py-2 px-4 text-sm"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <span class="text-gray-700">Run locally with: <code class="bg-gray-300 px-2 py-1 rounded">python3 -m http.server 8000</code></span> | |
| <a href="https://github.com/yourusername/pixelpulse-gallery" class="text-indigo-600 hover:text-indigo-800 flex items-center"> | |
| <i data-feather="github" class="mr-1"></i> View on GitHub | |
| </a> | |
| </div> | |
| </nav> | |
| <!-- Header --> | |
| <header class="bg-gradient-to-r from-indigo-500 to-purple-600 text-white py-6 shadow-lg"> | |
| <div class="container mx-auto px-4"> | |
| <div class="flex justify-between items-center"> | |
| <h1 class="text-3xl font-bold">PixelPulse Gallery</h1> | |
| <div class="flex space-x-4"> | |
| <button class="bg-white text-indigo-600 px-4 py-2 rounded-full font-semibold hover:bg-indigo-100 transition"> | |
| <i data-feather="upload" class="inline mr-2"></i> Upload | |
| </button> | |
| <button class="bg-indigo-700 text-white px-4 py-2 rounded-full font-semibold hover:bg-indigo-800 transition"> | |
| <i data-feather="user" class="inline mr-2"></i> Profile | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="container mx-auto px-4 py-8"> | |
| <!-- Search and Filter --> | |
| <div class="mb-8"> | |
| <div class="flex flex-col md:flex-row justify-between items-center gap-4"> | |
| <div class="relative w-full md:w-1/3"> | |
| <input type="text" placeholder="Search photos..." | |
| class="w-full pl-10 pr-4 py-2 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
| <i data-feather="search" class="absolute left-3 top-2.5 text-gray-400"></i> | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button class="px-4 py-2 bg-white rounded-full border border-gray-300 hover:bg-gray-50 flex items-center"> | |
| <i data-feather="filter" class="mr-2"></i> Filter | |
| </button> | |
| <button class="px-4 py-2 bg-white rounded-full border border-gray-300 hover:bg-gray-50 flex items-center"> | |
| <i data-feather="calendar" class="mr-2"></i> Date | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Gallery Grid --> | |
| <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> | |
| <!-- Sample photos - in a real app these would be dynamic --> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/nature/640x360/1')"> | |
| <img src="http://static.photos/nature/640x360/1" alt="Nature" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">Mountain View</h3> | |
| <p class="text-gray-600 text-sm">June 12, 2023</p> | |
| </div> | |
| </div> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/cityscape/640x360/2')"> | |
| <img src="http://static.photos/cityscape/640x360/2" alt="City" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">City Lights</h3> | |
| <p class="text-gray-600 text-sm">May 28, 2023</p> | |
| </div> | |
| </div> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/travel/640x360/3')"> | |
| <img src="http://static.photos/travel/640x360/3" alt="Travel" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">Beach Sunset</h3> | |
| <p class="text-gray-600 text-sm">April 15, 2023</p> | |
| </div> | |
| </div> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/food/640x360/4')"> | |
| <img src="http://static.photos/food/640x360/4" alt="Food" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">Delicious Meal</h3> | |
| <p class="text-gray-600 text-sm">March 22, 2023</p> | |
| </div> | |
| </div> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/people/640x360/5')"> | |
| <img src="http://static.photos/people/640x360/5" alt="People" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">Family Gathering</h3> | |
| <p class="text-gray-600 text-sm">February 18, 2023</p> | |
| </div> | |
| </div> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/technology/640x360/6')"> | |
| <img src="http://static.photos/technology/640x360/6" alt="Tech" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">Tech Setup</h3> | |
| <p class="text-gray-600 text-sm">January 5, 2023</p> | |
| </div> | |
| </div> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/vintage/640x360/7')"> | |
| <img src="http://static.photos/vintage/640x360/7" alt="Vintage" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">Retro Vibes</h3> | |
| <p class="text-gray-600 text-sm">December 12, 2022</p> | |
| </div> | |
| </div> | |
| <div class="gallery-item bg-white rounded-xl overflow-hidden shadow-md cursor-pointer" onclick="openModal('http://static.photos/outdoor/640x360/8')"> | |
| <img src="http://static.photos/outdoor/640x360/8" alt="Outdoor" class="w-full h-48 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-semibold">Hiking Adventure</h3> | |
| <p class="text-gray-600 text-sm">November 8, 2022</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Modal --> | |
| <div id="imageModal" class="fixed inset-0 z-50 flex items-center justify-center modal-overlay hidden"> | |
| <div class="relative"> | |
| <button onclick="closeModal()" class="absolute -top-10 right-0 text-white hover:text-gray-300 nav-button"> | |
| <i data-feather="x" class="w-8 h-8"></i> | |
| </button> | |
| <img id="modalImage" src="" alt="" class="modal-image rounded-lg"> | |
| <div class="flex justify-between mt-4"> | |
| <button onclick="prevImage()" class="bg-white p-3 rounded-full shadow-md nav-button"> | |
| <i data-feather="chevron-left" class="w-6 h-6"></i> | |
| </button> | |
| <button onclick="nextImage()" class="bg-white p-3 rounded-full shadow-md nav-button"> | |
| <i data-feather="chevron-right" class="w-6 h-6"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Footer --> | |
| <footer class="bg-gray-800 text-white py-6 mt-8"> | |
| <div class="container mx-auto px-4 text-center"> | |
| <p class="mb-2">© 2023 PixelPulse Gallery. All rights reserved.</p> | |
| <div class="flex justify-center space-x-4"> | |
| <a href="#" class="hover:text-indigo-300"><i data-feather="instagram"></i></a> | |
| <a href="#" class="hover:text-indigo-300"><i data-feather="twitter"></i></a> | |
| <a href="#" class="hover:text-indigo-300"><i data-feather="facebook"></i></a> | |
| <a href="#" class="hover:text-indigo-300"><i data-feather="github"></i></a> | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| // Simple instructions alert on first visit | |
| if (!localStorage.getItem('visited')) { | |
| alert('To run this site locally:\n1. Save this file as index.html\n2. Run: python3 -m http.server 8000\n3. Open http://localhost:8000 in your browser'); | |
| localStorage.setItem('visited', 'true'); | |
| } | |
| // For demonstration purposes - in a real app this would be dynamic | |
| const images = [ | |
| 'http://static.photos/nature/640x360/1', | |
| 'http://static.photos/cityscape/640x360/2', | |
| 'http://static.photos/travel/640x360/3', | |
| 'http://static.photos/food/640x360/4', | |
| 'http://static.photos/people/640x360/5', | |
| 'http://static.photos/technology/640x360/6', | |
| 'http://static.photos/vintage/640x360/7', | |
| 'http://static.photos/outdoor/640x360/8' | |
| ]; | |
| let currentImageIndex = 0; | |
| function openModal(imgSrc) { | |
| const modal = document.getElementById('imageModal'); | |
| const modalImg = document.getElementById('modalImage'); | |
| currentImageIndex = images.indexOf(imgSrc); | |
| modalImg.src = imgSrc; | |
| modal.classList.remove('hidden'); | |
| document.body.style.overflow = 'hidden'; | |
| } | |
| function closeModal() { | |
| const modal = document.getElementById('imageModal'); | |
| modal.classList.add('hidden'); | |
| document.body.style.overflow = 'auto'; | |
| } | |
| function nextImage() { | |
| currentImageIndex = (currentImageIndex + 1) % images.length; | |
| document.getElementById('modalImage').src = images[currentImageIndex]; | |
| } | |
| function prevImage() { | |
| currentImageIndex = (currentImageIndex - 1 + images.length) % images.length; | |
| document.getElementById('modalImage').src = images[currentImageIndex]; | |
| } | |
| // Close modal when clicking outside the image | |
| document.getElementById('imageModal').addEventListener('click', function(e) { | |
| if (e.target === this) { | |
| closeModal(); | |
| } | |
| }); | |
| // Keyboard navigation | |
| document.addEventListener('keydown', function(e) { | |
| const modal = document.getElementById('imageModal'); | |
| if (!modal.classList.contains('hidden')) { | |
| if (e.key === 'Escape') { | |
| closeModal(); | |
| } else if (e.key === 'ArrowRight') { | |
| nextImage(); | |
| } else if (e.key === 'ArrowLeft') { | |
| prevImage(); | |
| } | |
| } | |
| }); | |
| // Initialize feather icons | |
| feather.replace(); | |
| </script> | |
| </body> | |
| </html> | |