fix: walkthrough scrollytelling rewrite - sticky pin dwell, observer cleanup
All checks were successful
Deploy Website / deploy (push) Successful in 3s
All checks were successful
Deploy Website / deploy (push) Successful in 3s
- Replace scroll-snap with sticky pin wrappers (120vh dwell per step) - Steps stick at 25vh while user scrolls through wrapper height - IntersectionObserver now watches pin wrappers, clears data-step on exit - Sidebar animates in at step 0, hides when scrolling away - Remove aggressive scroll-snap-type from html - Tablet/mobile: fallback to relative positioning with fixed heights
This commit is contained in:
60
index.html
60
index.html
@@ -453,11 +453,17 @@
|
|||||||
flex: 0 0 360px;
|
flex: 0 0 360px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.wt-step {
|
.wt-step-pin {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.wt-step-pin:last-child {
|
||||||
min-height: 80vh;
|
min-height: 80vh;
|
||||||
|
}
|
||||||
|
.wt-step {
|
||||||
|
position: sticky;
|
||||||
|
top: 25vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
|
||||||
padding: 40px 0;
|
padding: 40px 0;
|
||||||
opacity: 0.12;
|
opacity: 0.12;
|
||||||
transform: translateY(16px);
|
transform: translateY(16px);
|
||||||
@@ -466,8 +472,6 @@
|
|||||||
transform 0.6s cubic-bezier(0.16, 1, 0.3, 1),
|
transform 0.6s cubic-bezier(0.16, 1, 0.3, 1),
|
||||||
filter 0.6s cubic-bezier(0.16, 1, 0.3, 1);
|
filter 0.6s cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
}
|
}
|
||||||
.wt-step:first-child { padding-top: 0; }
|
|
||||||
.wt-step:last-child { min-height: 60vh; }
|
|
||||||
.wt-step.active {
|
.wt-step.active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: none;
|
transform: none;
|
||||||
@@ -584,6 +588,7 @@
|
|||||||
transform: translateX(-20px);
|
transform: translateX(-20px);
|
||||||
transition: opacity 0.5s ease, transform 0.5s ease;
|
transition: opacity 0.5s ease, transform 0.5s ease;
|
||||||
}
|
}
|
||||||
|
.walkthrough[data-step="0"] .wt-sidebar,
|
||||||
.walkthrough[data-step="1"] .wt-sidebar,
|
.walkthrough[data-step="1"] .wt-sidebar,
|
||||||
.walkthrough[data-step="2"] .wt-sidebar,
|
.walkthrough[data-step="2"] .wt-sidebar,
|
||||||
.walkthrough[data-step="3"] .wt-sidebar {
|
.walkthrough[data-step="3"] .wt-sidebar {
|
||||||
@@ -784,15 +789,18 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
.wt-step-pin { min-height: auto; }
|
||||||
.wt-step {
|
.wt-step {
|
||||||
min-height: 70vh;
|
position: relative;
|
||||||
padding: 32px 0;
|
top: auto;
|
||||||
|
height: 80vh;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 32px 16px;
|
||||||
background: linear-gradient(180deg, rgba(244,237,243,0.95) 0%, rgba(244,237,243,0.8) 80%, transparent 100%);
|
background: linear-gradient(180deg, rgba(244,237,243,0.95) 0%, rgba(244,237,243,0.8) 80%, transparent 100%);
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
padding-left: 16px;
|
|
||||||
padding-right: 16px;
|
|
||||||
}
|
}
|
||||||
.wt-step:first-child { padding-top: 24px; }
|
.wt-step:first-child { padding-top: 24px; }
|
||||||
|
.wt-step:last-child { height: 60vh; }
|
||||||
.wt-step.active { filter: blur(0px); }
|
.wt-step.active { filter: blur(0px); }
|
||||||
.wt-app { min-height: 260px; }
|
.wt-app { min-height: 260px; }
|
||||||
.wt-main { padding: 20px 24px; }
|
.wt-main { padding: 20px 24px; }
|
||||||
@@ -805,9 +813,10 @@
|
|||||||
.walkthrough-inner { padding: 0 16px; }
|
.walkthrough-inner { padding: 0 16px; }
|
||||||
.wt-device { top: 68px; }
|
.wt-device { top: 68px; }
|
||||||
.wt-step {
|
.wt-step {
|
||||||
min-height: 55vh;
|
height: 75vh;
|
||||||
padding: 20px 12px;
|
padding: 20px 12px;
|
||||||
}
|
}
|
||||||
|
.wt-step:last-child { height: 55vh; }
|
||||||
.wt-app { min-height: 200px; font-size: 11px; }
|
.wt-app { min-height: 200px; font-size: 11px; }
|
||||||
.wt-main { padding: 16px 18px; }
|
.wt-main { padding: 16px 18px; }
|
||||||
.wt-greeting-name { font-size: 20px; }
|
.wt-greeting-name { font-size: 20px; }
|
||||||
@@ -1105,30 +1114,37 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ═══════ APP WALKTHROUGH — Sticky Scroll ═══════ -->
|
<!-- ═══════ APP WALKTHROUGH — Sticky Scroll ═══════ -->
|
||||||
<section class="walkthrough" id="walkthrough" data-step="0">
|
<section class="walkthrough" id="walkthrough">
|
||||||
<div class="wt-progress" id="wt-progress"></div>
|
<div class="wt-progress" id="wt-progress"></div>
|
||||||
<div class="walkthrough-inner">
|
<div class="walkthrough-inner">
|
||||||
|
|
||||||
<!-- Text column -->
|
<!-- Text column -->
|
||||||
<div class="wt-text">
|
<div class="wt-text">
|
||||||
|
<div class="wt-step-pin">
|
||||||
<div class="wt-step" data-step="0">
|
<div class="wt-step" data-step="0">
|
||||||
<p class="wt-step-num">The problem</p>
|
<p class="wt-step-num">The problem</p>
|
||||||
<h3>Your important emails hide between newsletters.</h3>
|
<h3>Your important emails hide between newsletters.</h3>
|
||||||
<p>You miss deadlines buried in threads. Tasks get lost across three different apps. Sound familiar?</p>
|
<p>You miss deadlines buried in threads. Tasks get lost across three different apps. Sound familiar?</p>
|
||||||
<div class="wt-dots"><span class="wt-dot active"></span><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot"></span></div>
|
<div class="wt-dots"><span class="wt-dot active"></span><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot"></span></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wt-step-pin">
|
||||||
<div class="wt-step" data-step="1">
|
<div class="wt-step" data-step="1">
|
||||||
<p class="wt-step-num">The greeting</p>
|
<p class="wt-step-num">The greeting</p>
|
||||||
<h3>Every morning, your AI secretary is ready.</h3>
|
<h3>Every morning, your AI secretary is ready.</h3>
|
||||||
<p>Open the app and it already knows what happened overnight — emails scanned, tasks prioritized, deadlines flagged.</p>
|
<p>Open the app and it already knows what happened overnight — emails scanned, tasks prioritized, deadlines flagged.</p>
|
||||||
<div class="wt-dots"><span class="wt-dot"></span><span class="wt-dot active"></span><span class="wt-dot"></span><span class="wt-dot"></span></div>
|
<div class="wt-dots"><span class="wt-dot"></span><span class="wt-dot active"></span><span class="wt-dot"></span><span class="wt-dot"></span></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wt-step-pin">
|
||||||
<div class="wt-step" data-step="2">
|
<div class="wt-step" data-step="2">
|
||||||
<p class="wt-step-num">The brief</p>
|
<p class="wt-step-num">The brief</p>
|
||||||
<h3>Meeting notes sit in a doc you'll never open again.</h3>
|
<h3>Meeting notes sit in a doc you'll never open again.</h3>
|
||||||
<p>Not here. Your daily brief is a clear, AI-generated summary of what matters today — tasks, follow-ups, and deadlines in one place.</p>
|
<p>Not here. Your daily brief is a clear, AI-generated summary of what matters today — tasks, follow-ups, and deadlines in one place.</p>
|
||||||
<div class="wt-dots"><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot active"></span><span class="wt-dot"></span></div>
|
<div class="wt-dots"><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot active"></span><span class="wt-dot"></span></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="wt-step-pin">
|
||||||
<div class="wt-step" data-step="3">
|
<div class="wt-step" data-step="3">
|
||||||
<p class="wt-step-num">The result</p>
|
<p class="wt-step-num">The result</p>
|
||||||
<h3 class="emphasis">You don't need another tool.<br>You need <em>a secretary</em>.</h3>
|
<h3 class="emphasis">You don't need another tool.<br>You need <em>a secretary</em>.</h3>
|
||||||
@@ -1136,6 +1152,7 @@
|
|||||||
<div class="wt-dots"><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot active"></span></div>
|
<div class="wt-dots"><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot"></span><span class="wt-dot active"></span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Device column -->
|
<!-- Device column -->
|
||||||
<div class="wt-device">
|
<div class="wt-device">
|
||||||
@@ -1431,25 +1448,32 @@
|
|||||||
const wtProgress = document.getElementById('wt-progress');
|
const wtProgress = document.getElementById('wt-progress');
|
||||||
|
|
||||||
if (wtSection && wtSteps.length) {
|
if (wtSection && wtSteps.length) {
|
||||||
// Set first step active
|
// IntersectionObserver for step activation (observe pin wrappers)
|
||||||
wtSteps[0].classList.add('active');
|
const wtPins = document.querySelectorAll('.wt-step-pin');
|
||||||
|
const activeSteps = new Set();
|
||||||
// IntersectionObserver for step activation
|
|
||||||
const stepObserver = new IntersectionObserver((entries) => {
|
const stepObserver = new IntersectionObserver((entries) => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
|
const stepEl = entry.target.querySelector('.wt-step');
|
||||||
|
const step = stepEl.getAttribute('data-step');
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
const step = entry.target.getAttribute('data-step');
|
activeSteps.add(step);
|
||||||
wtSteps.forEach(s => s.classList.remove('active'));
|
wtSteps.forEach(s => s.classList.remove('active'));
|
||||||
entry.target.classList.add('active');
|
stepEl.classList.add('active');
|
||||||
wtSection.setAttribute('data-step', step);
|
wtSection.setAttribute('data-step', step);
|
||||||
|
} else {
|
||||||
|
activeSteps.delete(step);
|
||||||
|
stepEl.classList.remove('active');
|
||||||
|
if (activeSteps.size === 0) {
|
||||||
|
wtSection.removeAttribute('data-step');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, {
|
}, {
|
||||||
rootMargin: '-40% 0px -40% 0px',
|
rootMargin: '-45% 0px -45% 0px',
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
wtSteps.forEach(step => stepObserver.observe(step));
|
wtPins.forEach(pin => stepObserver.observe(pin));
|
||||||
|
|
||||||
// Scroll progress indicator
|
// Scroll progress indicator
|
||||||
if (wtProgress) {
|
if (wtProgress) {
|
||||||
|
|||||||
Reference in New Issue
Block a user