footer : fix show/hide logic, transition and scroll throttle. related to #51
All checks were successful
Deploy / Deploy to Production (push) Successful in 23s
All checks were successful
Deploy / Deploy to Production (push) Successful in 23s
- Fix scroll listener (cleanup, local querySelector, scrollHeight calc) - Fix media query syntax in variables.css (missing space in `and (`) - Use transform: translateY instead of bottom for GPU-accelerated transition - Throttle scroll handler with requestAnimationFrame - Move Footer to App.svelte (global), remove per-view imports refs #51 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
77a1c58573
commit
0afbcf4088
9 changed files with 48 additions and 53 deletions
|
|
@ -2,38 +2,45 @@
|
|||
import { site } from '@state/site.svelte'
|
||||
import { locale } from '@state/locale.svelte'
|
||||
import { t } from '@i18n'
|
||||
import { slides } from '@state/slides.svelte'
|
||||
|
||||
const logo = $derived(site.logo)
|
||||
const title = $derived(site.title || 'World Game')
|
||||
const contact = $derived(site.contact || {})
|
||||
const socials = $derived(contact.socials ?? [])
|
||||
const year = new Date().getFullYear()
|
||||
let isHidden = $state(true)
|
||||
|
||||
let email = $state('')
|
||||
let status = $state(null)
|
||||
$effect(() => {
|
||||
const activeSlide = document.querySelector('.slide[data-slide="' + slides.active?.id + '"]')
|
||||
const scrollableContainer = activeSlide?.querySelector('.page-scrollable')
|
||||
|
||||
async function handleSubscribe(e) {
|
||||
e.preventDefault()
|
||||
if (!email) return
|
||||
try {
|
||||
const res = await fetch('/newsletter.json', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email })
|
||||
isHidden = true
|
||||
|
||||
if (!scrollableContainer) return
|
||||
|
||||
let rafId = null
|
||||
function onScroll() {
|
||||
if (rafId) return
|
||||
rafId = requestAnimationFrame(() => {
|
||||
const threshold = window.innerWidth > 800 ? 100 : 200
|
||||
const atBottom = scrollableContainer.scrollTop >= scrollableContainer.scrollHeight - scrollableContainer.clientHeight - threshold
|
||||
isHidden = !atBottom
|
||||
rafId = null
|
||||
})
|
||||
if (res.ok) {
|
||||
status = { type: 'success', message: t('newsletter_success') }
|
||||
email = ''
|
||||
} else {
|
||||
status = { type: 'error', message: t('newsletter_error') }
|
||||
}
|
||||
} catch {
|
||||
status = { type: 'error', message: t('newsletter_error') }
|
||||
}
|
||||
}
|
||||
|
||||
scrollableContainer.addEventListener('scroll', onScroll)
|
||||
onScroll()
|
||||
|
||||
return () => {
|
||||
scrollableContainer.removeEventListener('scroll', onScroll)
|
||||
if (rafId) cancelAnimationFrame(rafId)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<footer class="page-scrollable-footer">
|
||||
<footer class={["page-scrollable-footer", {hidden: isHidden}]}>
|
||||
<div class="footer-main">
|
||||
|
||||
<!-- Logo -->
|
||||
|
|
@ -98,18 +105,17 @@
|
|||
|
||||
<style>
|
||||
footer {
|
||||
position: absolute;
|
||||
width: 100vw;
|
||||
bottom: 0;
|
||||
background: #0d0e22;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
:global(.collection .page-scrollable-footer) {
|
||||
margin-left: -10.3rem;
|
||||
margin-top: 5rem;
|
||||
|
||||
transition: transform .3s var(--ease-standard);
|
||||
}
|
||||
|
||||
:global(.article-wrapper .page-scrollable-footer) {
|
||||
margin-left: -3.3rem;
|
||||
footer.hidden {
|
||||
transform: translateY(var(--footer-height));
|
||||
}
|
||||
|
||||
/* --- Main row --- */
|
||||
|
|
@ -222,17 +228,6 @@
|
|||
width: 7%;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
:global(.collection .page-scrollable-footer) {
|
||||
margin-left: -1.5rem;
|
||||
}
|
||||
:global(.article-wrapper .page-scrollable-footer) {
|
||||
margin-left: -1.3rem;
|
||||
}
|
||||
|
||||
:global(.about .page-scrollable-footer) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Tablet (701px–912px) --- */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue