166 lines
4.8 KiB
Svelte
166 lines
4.8 KiB
Svelte
<style lang="scss">
|
|
@import "../../style/pages/shop/intro";
|
|
</style>
|
|
|
|
<script lang="ts">
|
|
import { navigating } from '$app/stores'
|
|
import { getContext, onMount } from 'svelte'
|
|
import { stagger, timeline } from 'motion'
|
|
import { smoothScroll } from '$utils/stores'
|
|
import { cartOpen } from '$utils/stores/shop'
|
|
import { DELAY } from '$utils/contants'
|
|
import { quartOut } from '$animations/easings'
|
|
// Components
|
|
import Image from '$components/atoms/Image.svelte'
|
|
import ButtonCart from '$components/atoms/ButtonCart.svelte'
|
|
import ShopLocationSwitcher from '$components/molecules/ShopLocationSwitcher.svelte'
|
|
|
|
export let product: any = undefined
|
|
|
|
const { shop, shopLocations }: any = getContext('shop')
|
|
|
|
let innerWidth: number
|
|
let navObserver: IntersectionObserver
|
|
let introEl: HTMLElement, navChooseEl: HTMLElement
|
|
let scrolledPastIntro = false
|
|
|
|
|
|
onMount(() => {
|
|
// Reveal the nav past the Intro
|
|
navObserver = new IntersectionObserver(entries => {
|
|
entries.forEach(entry => {
|
|
scrolledPastIntro = !entry.isIntersecting
|
|
})
|
|
}, {
|
|
threshold: 0,
|
|
rootMargin: '-3% 0px 0px'
|
|
})
|
|
navObserver.observe(introEl)
|
|
|
|
// Set navigation horizontal scroll depending on current link position
|
|
const navChooseActive: HTMLElement = navChooseEl.querySelector('.is-active')
|
|
const offsetLeft = navChooseActive.offsetLeft
|
|
|
|
if (offsetLeft > window.innerWidth / 2) {
|
|
navChooseEl.scrollLeft = offsetLeft
|
|
}
|
|
|
|
|
|
/**
|
|
* Animations
|
|
*/
|
|
const animation = timeline([
|
|
// Hero image
|
|
['.shop-page__background', {
|
|
scale: [1.06, 1],
|
|
opacity: [0, 1],
|
|
z: 0,
|
|
}, {
|
|
at: 0.4,
|
|
duration: 2.4,
|
|
}],
|
|
|
|
// Intro top elements
|
|
['.shop-page__intro .top > *', {
|
|
y: [-100, 0],
|
|
opacity: [0, 1],
|
|
}, {
|
|
at: 0.4,
|
|
delay: stagger(0.25),
|
|
}],
|
|
|
|
// Hero title
|
|
['.shop-page__title h1', {
|
|
y: [32, 0],
|
|
opacity: [0, 1],
|
|
}, {
|
|
at: 0.5,
|
|
}],
|
|
|
|
// Intro navbar
|
|
['.shop-page__nav .container > *, .shop-page__intro .button-cart', {
|
|
y: [100, 0],
|
|
opacity: [0, 1],
|
|
}, {
|
|
at: 0.7,
|
|
delay: stagger(0.25),
|
|
}]
|
|
], {
|
|
delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
|
|
defaultOptions: {
|
|
duration: 1.6,
|
|
easing: quartOut,
|
|
},
|
|
})
|
|
animation.stop()
|
|
|
|
// Run animation
|
|
requestAnimationFrame(animation.play)
|
|
|
|
|
|
// Destroy
|
|
return () => {
|
|
navObserver && navObserver.disconnect()
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<svelte:window bind:innerWidth />
|
|
|
|
|
|
<section class="shop-page__intro" bind:this={introEl}>
|
|
<div class="top container">
|
|
<a href="/" class="back" data-sveltekit-noscroll>
|
|
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M4 1 1 4l3 3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
|
</svg>
|
|
<span>Back to Houses Of</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="shop-page__title">
|
|
<h1 class="title-big-sans">Shop</h1>
|
|
</div>
|
|
|
|
<nav class="shop-page__nav">
|
|
<div class="container">
|
|
<p class="text-label">Choose a city</p>
|
|
<nav>
|
|
<ul data-sveltekit-noscroll data-sveltekit-prefetch bind:this={navChooseEl}>
|
|
{#each shopLocations as { name, slug }}
|
|
<li class:is-active={product && slug === product.location.slug}>
|
|
<a href="/shop/poster-{slug}" on:click={() => $smoothScroll.scrollTo('#poster', { duration: 2 })}>
|
|
{name}
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</nav>
|
|
|
|
<ButtonCart />
|
|
|
|
<Image
|
|
class="shop-page__background"
|
|
id={shop.page_heroimage.id}
|
|
alt={shop.page_heroimage.alt}
|
|
sizeKey="hero"
|
|
sizes={{
|
|
large: { width: 1800, height: 1200 },
|
|
medium: { width: 1200, height: 800 },
|
|
small: { width: 700, height: 700 },
|
|
}}
|
|
lazy={false}
|
|
/>
|
|
</section>
|
|
|
|
<nav class="shop-location"
|
|
class:is-visible={scrolledPastIntro}
|
|
class:is-overlaid={$cartOpen}
|
|
>
|
|
{#if innerWidth > 768}
|
|
<ShopLocationSwitcher />
|
|
{/if}
|
|
<ButtonCart />
|
|
</nav> |