From d48204547f5b54776e0b0b51ed590db91226a8e9 Mon Sep 17 00:00:00 2001 From: Roshan Bhagtani Date: Sun, 26 Oct 2025 19:36:47 +0530 Subject: [PATCH] feat: Add auto-cycle slideshow with play/pause controls --- expanding-cards/index.html | 18 ++++--- expanding-cards/script.js | 106 +++++++++++++++++++++++++++++++++---- expanding-cards/style.css | 40 ++++++++++++-- 3 files changed, 144 insertions(+), 20 deletions(-) diff --git a/expanding-cards/index.html b/expanding-cards/index.html index 164951d..355733c 100644 --- a/expanding-cards/index.html +++ b/expanding-cards/index.html @@ -7,25 +7,29 @@ Expanding Cards +
+ + +
+
-
+

Explore The World

-
+

Wild Forest

-
+

Sunny Beach

-
+

City on Winter

-
+

Mountains - Clouds

-
- + \ No newline at end of file diff --git a/expanding-cards/script.js b/expanding-cards/script.js index 68d6b5c..c31c334 100644 --- a/expanding-cards/script.js +++ b/expanding-cards/script.js @@ -1,14 +1,100 @@ -const panels = document.querySelectorAll('.panel') +const panels = document.querySelectorAll('.panel'); +const playBtn = document.getElementById('play-btn'); +const pauseBtn = document.getElementById('pause-btn'); -panels.forEach(panel => { - panel.addEventListener('click', () => { - removeActiveClasses() - panel.classList.add('active') - }) -}) +let currentActive = 0; // Track the index of the currently active panel +let intervalId = null; // To store the interval timer + +// --- Core Functions --- + +// Function to set a specific panel as active +function setActivePanel(index) { + removeActiveClasses(); + if (panels[index]) { // Check if the panel exists + panels[index].classList.add('active'); + currentActive = index; + } +} +// Function to remove active classes from all panels function removeActiveClasses() { panels.forEach(panel => { - panel.classList.remove('active') - }) -} \ No newline at end of file + panel.classList.remove('active'); + }); +} + +// Function to start the auto-cycle +function startAutoCycle() { + if (intervalId === null) { // Only start if not already running + console.log("Starting auto-cycle"); // Debug log + intervalId = setInterval(() => { + let nextActive = (currentActive + 1) % panels.length; // Calculate next index, wraps around + setActivePanel(nextActive); + }, 3000); // Change panel every 3 seconds (3000ms) + } +} + +// Function to stop the auto-cycle +function stopAutoCycle() { + console.log("Stopping auto-cycle"); // Debug log + clearInterval(intervalId); + intervalId = null; // Reset intervalId +} + +// --- Event Listeners --- + +// Original click event listener (stops auto-cycle on manual click) +panels.forEach((panel, index) => { + panel.addEventListener('click', () => { + stopAutoCycle(); // Stop auto-play when user clicks + setActivePanel(index); + }); + + // Keyboard accessibility (Enter/Space) - stops auto-cycle + panel.addEventListener('keydown', (event) => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + stopAutoCycle(); + setActivePanel(index); + } + // Add arrow key logic here if you implemented it previously + if (event.key === 'ArrowLeft') { + event.preventDefault(); + stopAutoCycle(); // Stop auto-cycle on arrow key nav + const prevPanelIndex = (index - 1 + panels.length) % panels.length; + panels[prevPanelIndex].focus(); + // Optionally activate the focused panel immediately + // setActivePanel(prevPanelIndex); + } + if (event.key === 'ArrowRight') { + event.preventDefault(); + stopAutoCycle(); // Stop auto-cycle on arrow key nav + const nextPanelIndex = (index + 1) % panels.length; + panels[nextPanelIndex].focus(); + // Optionally activate the focused panel immediately + // setActivePanel(nextPanelIndex); + } + }); +}); + +// Event listener for Play button +playBtn.addEventListener('click', () => { + // Ensure the current one is visually active before starting + if (!panels[currentActive].classList.contains('active')) { + setActivePanel(currentActive); + } + startAutoCycle(); +}); + +// Event listener for Pause button +pauseBtn.addEventListener('click', () => { + stopAutoCycle(); +}); + +// --- Initial Setup --- +// Find the initially active panel from the HTML to set the starting index +panels.forEach((panel, index) => { + if (panel.classList.contains('active')) { + currentActive = index; + } +}); \ No newline at end of file diff --git a/expanding-cards/style.css b/expanding-cards/style.css index a6fe024..a0f7f2f 100644 --- a/expanding-cards/style.css +++ b/expanding-cards/style.css @@ -6,7 +6,9 @@ body { font-family: 'Muli', sans-serif; + /* Adjust display to allow space for controls */ display: flex; + flex-direction: column; /* Stack controls above container */ align-items: center; justify-content: center; height: 100vh; @@ -30,7 +32,7 @@ body { flex: 0.5; margin: 10px; position: relative; - -webkit-transition: all 700ms ease-in; + transition: all 700ms ease-in, outline 0.1s linear; /* Keep existing transition */ } .panel h3 { @@ -40,6 +42,9 @@ body { left: 20px; margin: 0; opacity: 0; + /* Add slide animation styles */ + transform: translateY(30px); + transition: opacity 0.3s ease-in 0.4s, transform 0.4s ease-in 0.4s; } .panel.active { @@ -48,9 +53,38 @@ body { .panel.active h3 { opacity: 1; - transition: opacity 0.3s ease-in 0.4s; + transform: translateY(0); /* Final position for slide animation */ + /* Remove transition from here as it's handled by base .panel h3 */ } +.panel:focus { + outline: 3px solid #fff; + outline-offset: -3px; +} + +/* --- ADDED Styles for Auto-Cycle Controls --- */ +.controls { + text-align: center; + margin-bottom: 20px; /* Add space between buttons and cards */ +} + +.controls button { + background-color: #eee; + border: none; + padding: 10px 20px; + margin: 0 10px; + border-radius: 5px; + cursor: pointer; + font-size: 1rem; + transition: background-color 0.3s ease; +} + +.controls button:hover { + background-color: #ddd; +} +/* --- End of Added Styles --- */ + + @media (max-width: 480px) { .container { width: 100vw; @@ -60,4 +94,4 @@ body { .panel:nth-of-type(5) { display: none; } -} +} \ No newline at end of file