ELF-457: add slot 3 rotating tagline above hero sub on hatch.surf
Some checks failed
CI / go (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / lint-go (push) Has been cancelled
CI / lint-docs (push) Has been cancelled
CI / check-paperclip (push) Has been cancelled
Deploy static site / Deploy to GitHub Pages (push) Has been cancelled
Deploy static site / Deploy via Docker to hatch.surf (push) Has been cancelled
Some checks failed
CI / go (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / lint-go (push) Has been cancelled
CI / lint-docs (push) Has been cancelled
CI / check-paperclip (push) Has been cancelled
Deploy static site / Deploy to GitHub Pages (push) Has been cancelled
Deploy static site / Deploy via Docker to hatch.surf (push) Has been cancelled
Three taglines rotate every 3.5s with a subtle 700ms opacity crossfade between the H1 and the hero sub on the hatch.surf landing page: 1. Inspect any request. Mock any response. (default, in initial HTML) 2. Your HTTP bin, on your machine. 3. Send. Capture. Mock. No signup. Implementation: - site/index.html: <div class='hero-tagline' aria-live=polite> with three <p class='hero-tagline-item'> children stacked; default #1 has is-active class and no aria-hidden (for SEO + no-JS users) - site/style.css: .hero-tagline uses position:relative with fixed height: 1.7em (no CLS during rotation); absolute children crossfade via transition: opacity 700ms var(--ease-out); font: JetBrains Mono weight 500 in var(--text-secondary); clamp(0.85rem, 2.2vw, 1rem) so mobile (375px+) fits the longest tagline on one line - site/main.js: initRotatingTagline() in the existing IIFE; setInterval every 3500ms swaps is-active and aria-hidden between siblings; early-returns if prefers-reduced-motion is set, so the default tagline stays visible without animation - Spacing: H1 mb-sp-6, tagline mb-sp-6, sub mb-sp-8 keeps the existing 24px/24px/32px rhythm unchanged below the headline Note: site/index.html (not the Next.js app under app/ + components/) is what hatch.surf/nginx actually serves. The Next.js work from the earlier failed run was reverted.
This commit is contained in:
parent
bcb4f1688e
commit
478e2818b9
@ -67,6 +67,13 @@
|
|||||||
<h1 data-animate="fade-up" data-delay="80">
|
<h1 data-animate="fade-up" data-delay="80">
|
||||||
Self-hostable HTTP request<br>inspector + mocker
|
Self-hostable HTTP request<br>inspector + mocker
|
||||||
</h1>
|
</h1>
|
||||||
|
<!-- Slot 3 rotating tagline (ELF-457, brief ELF-456). Default #1 is in the
|
||||||
|
initial HTML for no-JS / SEO. JS in main.js cycles opacity every 3.5s. -->
|
||||||
|
<div class="hero-tagline" aria-live="polite" aria-atomic="true">
|
||||||
|
<p class="hero-tagline-item is-active">Inspect any request. Mock any response.</p>
|
||||||
|
<p class="hero-tagline-item" aria-hidden="true">Your HTTP bin, on your machine.</p>
|
||||||
|
<p class="hero-tagline-item" aria-hidden="true">Send. Capture. Mock. No signup.</p>
|
||||||
|
</div>
|
||||||
<p class="hero-sub" data-animate="fade-up" data-delay="160">
|
<p class="hero-sub" data-animate="fade-up" data-delay="160">
|
||||||
One Go binary. SQLite under the hood.<br>
|
One Go binary. SQLite under the hood.<br>
|
||||||
<code>docker compose up</code>, and you have an inspection endpoint and a live feed in under 30 seconds.
|
<code>docker compose up</code>, and you have an inspection endpoint and a live feed in under 30 seconds.
|
||||||
|
|||||||
26
site/main.js
26
site/main.js
@ -420,6 +420,32 @@
|
|||||||
|
|
||||||
initEntranceAnimations(animate, stagger);
|
initEntranceAnimations(animate, stagger);
|
||||||
initTerminalGlow(animate);
|
initTerminalGlow(animate);
|
||||||
|
initRotatingTagline();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Slot 3 rotating tagline (ELF-457)
|
||||||
|
// Cycles 3 tagline <p>s every 3.5s with a 700ms opacity crossfade
|
||||||
|
// (handled in CSS via .hero-tagline-item transition). Honors
|
||||||
|
// prefers-reduced-motion: skips the timer entirely so the default
|
||||||
|
// #1 stays visible without any animation.
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
function initRotatingTagline() {
|
||||||
|
var container = document.querySelector('.hero-tagline');
|
||||||
|
if (!container) return;
|
||||||
|
var items = container.querySelectorAll('.hero-tagline-item');
|
||||||
|
if (items.length < 2) return;
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||||
|
|
||||||
|
var idx = 0;
|
||||||
|
window.setInterval(function () {
|
||||||
|
items[idx].classList.remove('is-active');
|
||||||
|
items[idx].setAttribute('aria-hidden', 'true');
|
||||||
|
idx = (idx + 1) % items.length;
|
||||||
|
items[idx].classList.add('is-active');
|
||||||
|
items[idx].removeAttribute('aria-hidden');
|
||||||
|
}, 3500);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defer boot by one frame so anime.js engine is ready
|
// Defer boot by one frame so anime.js engine is ready
|
||||||
|
|||||||
@ -363,6 +363,43 @@ nav {
|
|||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Slot 3: rotating tagline (ELF-457). Sits between H1 and hero-sub.
|
||||||
|
Fixed height prevents CLS during rotation; absolute children crossfade. */
|
||||||
|
.hero-tagline {
|
||||||
|
position: relative;
|
||||||
|
max-width: 560px;
|
||||||
|
height: 1.7em;
|
||||||
|
margin: 0 auto var(--sp-6);
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: clamp(0.85rem, 2.2vw, 1rem);
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-tagline-item {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 700ms var(--ease-out);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-tagline-item.is-active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.hero-tagline-item {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.hero-sub {
|
.hero-sub {
|
||||||
font-size: clamp(1rem, 2vw, 1.2rem);
|
font-size: clamp(1rem, 2vw, 1.2rem);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user