Files
housesof/src/components/organisms/ShopBanner.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>