Home: navigazione, footer, CTA, servizi (Breaking Glass), scroll-spy
- Allinea scroll a #contatti, misura header e scroll-padding, spy con documentTopY e piccolo SPY_FUDGE; hashchange/ResizeObserver; footer visibile azzera Contattaci - Footer: id site-footer, griglia senza blocco brand sopra, tagline a destra del copyright; global.css fallback scroll-padding - CTA: eyebrow Contatti, bordo/sezione allineate alle FAQ, #contatti sulla section - Servizi: callout Breaking Glass con look glossy (gradient, highlight, luce) Made-with: Cursor
This commit is contained in:
@ -1,16 +1,38 @@
|
||||
/**
|
||||
* Home: evidenzia in bianco il link del menu che corrisponde alla sezione in vista.
|
||||
* `scrollPaddingTop` e l’altezza header hanno stesso valore. Lo spy usa +4px
|
||||
* (SPY_VIEWPORT_FUDGE_PX) così il collegamento attivo segue l’inizio sezione
|
||||
* a schermo, senza dover forzare altro scroll a mano.
|
||||
*/
|
||||
const SECTION_IDS = ['prodotti', 'servizi', 'stack', 'faq', 'contatti'] as const;
|
||||
const HEADER_OFFSET = 88;
|
||||
let headerOffset = 80;
|
||||
/** Soglia leggermente sotto l’inizio reale sezione, così il link si accende in linea con lo sguardo. */
|
||||
const SPY_VIEWPORT_FUDGE_PX = 4;
|
||||
|
||||
function documentTopY(el: Element): number {
|
||||
const { top } = el.getBoundingClientRect();
|
||||
return top + window.scrollY;
|
||||
}
|
||||
|
||||
function getActiveSectionId(): string | null {
|
||||
const y = window.scrollY + HEADER_OFFSET;
|
||||
// y = scrollY + (header reale) + leggera tolleranza: l’inizio sezione attraverso
|
||||
// l’orizzonte “link attivo” un poco prima del minimo in px.
|
||||
const y = window.scrollY + headerOffset + SPY_VIEWPORT_FUDGE_PX;
|
||||
let active: string | null = null;
|
||||
for (const id of SECTION_IDS) {
|
||||
const el = document.getElementById(id);
|
||||
if (!el) continue;
|
||||
if (el.offsetTop <= y) active = id;
|
||||
if (documentTopY(el) <= y) active = id;
|
||||
}
|
||||
// Fuori focus dalla CTA: quando entra in vista il footer, non evidenziare Contattaci.
|
||||
if (active === 'contatti') {
|
||||
const siteFooter = document.getElementById('site-footer');
|
||||
if (siteFooter) {
|
||||
const { top: footerTop } = siteFooter.getBoundingClientRect();
|
||||
if (footerTop < window.innerHeight) {
|
||||
active = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return active;
|
||||
}
|
||||
@ -36,15 +58,45 @@ function onScroll(): void {
|
||||
});
|
||||
}
|
||||
|
||||
function measureStickyBarHeight(): number {
|
||||
const header = document.querySelector<HTMLElement>('header');
|
||||
if (!header) return headerOffset;
|
||||
// Riga fissa o, se il menu mobile è aperto, pannello incluso: deve coincidere con
|
||||
// l’ingombro reale sotto al quale il main può iniziare.
|
||||
return Math.round(header.getBoundingClientRect().height);
|
||||
}
|
||||
|
||||
function measureHeaderAndSync(): void {
|
||||
headerOffset = measureStickyBarHeight();
|
||||
if (headerOffset > 0) {
|
||||
document.documentElement.style.scrollPaddingTop = `${headerOffset}px`;
|
||||
}
|
||||
applyActive();
|
||||
}
|
||||
|
||||
function bind(): void {
|
||||
const path = window.location.pathname;
|
||||
if (path !== '/' && path !== '/index.html') return;
|
||||
|
||||
applyActive();
|
||||
const header = document.querySelector('header');
|
||||
measureHeaderAndSync();
|
||||
const reflow = () => {
|
||||
requestAnimationFrame(() => {
|
||||
measureHeaderAndSync();
|
||||
});
|
||||
};
|
||||
reflow();
|
||||
if (header && 'ResizeObserver' in window) {
|
||||
new ResizeObserver(() => {
|
||||
reflow();
|
||||
}).observe(header);
|
||||
}
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
window.addEventListener('resize', onScroll, { passive: true });
|
||||
window.addEventListener('hashchange', applyActive);
|
||||
window.addEventListener('load', applyActive);
|
||||
window.addEventListener('resize', reflow, { passive: true });
|
||||
window.addEventListener('hashchange', () => {
|
||||
reflow();
|
||||
});
|
||||
window.addEventListener('load', reflow, { passive: true });
|
||||
}
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
|
||||
Reference in New Issue
Block a user