- Add ScrollToTop component matching main site's green Top button (appears after 130px scroll, same styling and font) - Fix main-site server.js: JS/CSS now use max-age=3600 + must-revalidate instead of 30d immutable — changes reach users within 1 hour instead of being stuck in browser cache for a month - Images/fonts keep 30d immutable (safe, as they are content-addressed) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
|
|
export default function ScrollToTop() {
|
|
const [visible, setVisible] = useState(false)
|
|
|
|
useEffect(() => {
|
|
const onScroll = () => {
|
|
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
|
|
setVisible(scrollTop > 130)
|
|
}
|
|
window.addEventListener('scroll', onScroll, { passive: true })
|
|
return () => window.removeEventListener('scroll', onScroll)
|
|
}, [])
|
|
|
|
if (!visible) return null
|
|
|
|
return (
|
|
<button
|
|
aria-label="Back to top"
|
|
onClick={() => window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })}
|
|
style={{
|
|
position: 'fixed',
|
|
bottom: '12px',
|
|
right: '10px',
|
|
zIndex: 99,
|
|
border: '1px solid #363636',
|
|
outline: 'none',
|
|
background: '#94d601',
|
|
cursor: 'pointer',
|
|
padding: '15px',
|
|
borderRadius: '10px',
|
|
fontSize: '18px',
|
|
boxShadow: '3px 3px 3px #363636',
|
|
fontFamily: '"Autour One", serif',
|
|
lineHeight: 1,
|
|
}}
|
|
onMouseEnter={(e) => { (e.currentTarget as HTMLButtonElement).style.background = '#aedad3' }}
|
|
onMouseLeave={(e) => { (e.currentTarget as HTMLButtonElement).style.background = '#94d601' }}
|
|
>
|
|
Top
|
|
</button>
|
|
)
|
|
}
|