diff --git a/demo/index.html b/demo/index.html index 536a11901..c424073dc 100644 --- a/demo/index.html +++ b/demo/index.html @@ -386,6 +386,11 @@ .js-story .story-intro > div { position: sticky; top: 0; height: 100svh; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; max-width: 58rem; margin: 0 auto; padding: 5rem 1.5rem 2rem; } .js-story .story-pin { height: 420vh; } .js-story .story-stage { position: sticky; top: 0; height: 100svh; min-height: 0; padding-top: 5.5rem; padding-bottom: 2rem; } + .story-hint { display: none; } + .js-story .story-hint { display: flex; align-items: center; gap: 0.5rem; margin: 2rem 0 0; font: 500 0.8rem/1 'JetBrains Mono', monospace; letter-spacing: 0.08em; text-transform: uppercase; color: rgb(var(--c-slate-400)); transition: opacity 0.4s; } + .js-story .story-hint.gone { opacity: 0; pointer-events: none; } + .story-hint span { display: inline-block; animation: story-nudge 1.6s ease-in-out infinite; } + @keyframes story-nudge { 0%, 100% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(0, 5px, 0); } } .js-story .story-words .w { color: rgb(var(--c-fg) / 0.16); } .js-story .story-words .w.lit { color: rgb(var(--c-fg)); } .js-story .story-verdict span { position: absolute; left: 0; top: 0; opacity: 0; transform: translate3d(0, 24px, 0); transition: opacity 0.5s, transform 0.6s cubic-bezier(0.16, 1, 0.3, 1); } @@ -561,6 +566,7 @@

Independent verification

An agent says it backed up the database. Joltrin checks the record, not the claim.

+

Scroll down to continue

@@ -2853,9 +2859,11 @@

${res.title}

var pin = story.querySelector('.story-pin'); var rows = story.querySelectorAll('.story-row'); var tagged = story.querySelectorAll('[data-for]'); + var hint = document.getElementById('story-hint'); var step = -1, ticking = false; function frame() { ticking = false; + if (hint) hint.classList.toggle('gone', window.scrollY > 40); var vh = window.innerHeight; // Words: lit across the pinned intro track. var r = intro.getBoundingClientRect(); diff --git a/tests/homepage.spec.ts b/tests/homepage.spec.ts index 5deca52a4..5e9eb6b88 100644 --- a/tests/homepage.spec.ts +++ b/tests/homepage.spec.ts @@ -287,6 +287,17 @@ test.describe('Homepage', () => { await expect(page.locator('.story-verdict .v-block')).not.toHaveClass(/show/); }); + test('a scroll hint shows at the top and goes away once the visitor scrolls', async ({ page }) => { + await page.goto('/', { waitUntil: 'domcontentloaded' }); + const hint = page.locator('#story-hint'); + await expect(hint).toBeVisible(); + await expect(hint).toContainText('Scroll down to continue'); + await page.evaluate(() => window.scrollTo(0, 200)); + await expect(hint).toHaveClass(/gone/); + await page.evaluate(() => window.scrollTo(0, 0)); + await expect(hint).not.toHaveClass(/gone/); + }); + test('reduced motion renders the finished story with no scripted pinning', async ({ page }) => { await page.emulateMedia({ reducedMotion: 'reduce' }); await page.goto('/', { waitUntil: 'domcontentloaded' }); @@ -297,6 +308,7 @@ test.describe('Homepage', () => { } const position = await page.locator('.story-stage').evaluate((el) => getComputedStyle(el).position); expect(position).not.toBe('sticky'); + await expect(page.locator('#story-hint')).toBeHidden(); }); });