refactor: use global page transition in main layout

This commit is contained in:
2023-05-26 23:49:23 +02:00
parent 685d4fd244
commit d991dad294
17 changed files with 864 additions and 908 deletions

View File

@@ -3,7 +3,6 @@
import { page } from '$app/stores'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import ShopHeader from '$components/organisms/ShopBanner.svelte'
import PostersGrid from '$components/organisms/PostersGrid.svelte'
@@ -25,19 +24,17 @@
/>
<PageTransition>
<main class="shop-page">
<ShopHeader />
<main class="shop-page">
<ShopHeader />
<section class="shop-page__error">
<div class="container grid">
<div class="inner">
<h2 class="title-big">Uh oh!</h2>
<p class="text-medium">{errors[$page.status].message}</p>
</div>
<section class="shop-page__error">
<div class="container grid">
<div class="inner">
<h2 class="title-big">Uh oh!</h2>
<p class="text-medium">{errors[$page.status].message}</p>
</div>
</section>
</div>
</section>
<PostersGrid {posters} />
</main>
</PageTransition>
<PostersGrid {posters} />
</main>

View File

@@ -3,7 +3,6 @@
import { getAssetUrlKey } from '$utils/api'
import { shopCurrentProductSlug } from '$utils/stores/shop'
// Components
import PageTransition from '$components/PageTransition.svelte'
import Metas from '$components/Metas.svelte'
import PostersGrid from '$components/organisms/PostersGrid.svelte'
import ShopHeader from '$components/organisms/ShopBanner.svelte'
@@ -25,15 +24,13 @@
/>
<PageTransition>
<main class="shop-page">
<ShopHeader {product} />
<main class="shop-page">
<ShopHeader {product} />
<PosterLayout
product={product}
shopProduct={shopProduct}
/>
<PosterLayout
product={product}
shopProduct={shopProduct}
/>
<PostersGrid {posters} />
</main>
</PageTransition>
<PostersGrid {posters} />
</main>

View File

@@ -4,7 +4,6 @@
import { shopCurrentProductSlug } from '$utils/stores/shop'
import { capitalizeFirstLetter } from 'utils/string'
// Components
import PageTransition from '$components/PageTransition.svelte'
import Metas from '$components/Metas.svelte'
import ShopHeader from '$components/organisms/ShopBanner.svelte'
import PostersGrid from '$components/organisms/PostersGrid.svelte'
@@ -24,15 +23,13 @@
/>
<PageTransition>
<main class="shop-page">
<ShopHeader product={data.product} />
<main class="shop-page">
<ShopHeader product={data.product} />
<PosterLayout
product={data.product}
shopProduct={data.shopProduct}
/>
<PosterLayout
product={data.product}
shopProduct={data.shopProduct}
/>
<PostersGrid {posters} />
</main>
</PageTransition>
<PostersGrid {posters} />
</main>

View File

@@ -16,7 +16,6 @@
import { PUBLIC_LIST_INCREMENT } from '$env/static/public'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import Image from '$components/atoms/Image.svelte'
import Button from '$components/atoms/Button.svelte'
import IconEarth from '$components/atoms/IconEarth.svelte'
@@ -218,149 +217,147 @@
/>
<PageTransition>
<main class="location-page">
<section class="location-page__intro grid" bind:this={introEl}>
<h1 class="title" class:is-short={location.name.length <= 4}>
<span class="housesof mask">
<strong class="word">Houses</strong>
<span class="of">of</span>
</span>
<strong class="city mask">
<span class="word">{location.name}</span>
</strong>
</h1>
<main class="location-page">
<section class="location-page__intro grid" bind:this={introEl}>
<h1 class="title" class:is-short={location.name.length <= 4}>
<span class="housesof mask">
<strong class="word">Houses</strong>
<span class="of">of</span>
</span>
<strong class="city mask">
<span class="word">{location.name}</span>
</strong>
</h1>
<div class="location-page__description grid">
<div class="wrap">
<div class="text-medium">
Houses of {location.name} {location.description ?? 'has no description yet'}
</div>
<div class="info">
<p class="text-label">
Photos by
{#each location.credits as { credit_id: { name, website } }}
{#if website}
<a href={website} target="_blank" rel="noopener external">
{name}
</a>
{:else}
<span>{name}</span>
{/if}
{/each}
<div class="location-page__description grid">
<div class="wrap">
<div class="text-medium">
Houses of {location.name} {location.description ?? 'has no description yet'}
</div>
<div class="info">
<p class="text-label">
Photos by
{#each location.credits as { credit_id: { name, website } }}
{#if website}
<a href={website} target="_blank" rel="noopener external">
{name}
</a>
{:else}
<span>{name}</span>
{/if}
{/each}
</p>
{#if latestPhoto}
&middot;
<p class="text-label" title={dayjs(latestPhoto.date_created).format('DD/MM/YYYY, hh:mm')}>
Updated <time datetime={dayjs(latestPhoto.date_created).format('YYYY-MM-DD')}>
{dayjs().to(dayjs(latestPhoto.date_created))}
</time>
</p>
{#if latestPhoto}
&middot;
<p class="text-label" title={dayjs(latestPhoto.date_created).format('DD/MM/YYYY, hh:mm')}>
Updated <time datetime={dayjs(latestPhoto.date_created).format('YYYY-MM-DD')}>
{dayjs().to(dayjs(latestPhoto.date_created))}
</time>
</p>
{/if}
</div>
{/if}
</div>
<div class="ctas">
<Button url="/locations" text="Change location" class="shadow-small">
<IconEarth />
<div class="ctas">
<Button url="/locations" text="Change location" class="shadow-small">
<IconEarth />
</Button>
{#if location.has_poster}
<Button url="/shop/poster-{location.slug}" text="Buy the poster" color="pinklight" class="shadow-small">
<!-- <IconEarth /> -->
</Button>
{#if location.has_poster}
<Button url="/shop/poster-{location.slug}" text="Buy the poster" color="pinklight" class="shadow-small">
<!-- <IconEarth /> -->
</Button>
{/if}
</div>
{/if}
</div>
</div>
</div>
{#if hasIllustration}
<picture class="location-page__illustration" style:--parallax-y="{illustrationOffsetY}px">
<source media="(min-width: 1200px)" srcset={getAssetUrlKey(location.illustration_desktop_2x.id, 'illustration-desktop-2x')}>
<source media="(min-width: 768px)" srcset={getAssetUrlKey(location.illustration_desktop.id, 'illustration-desktop-1x')}>
<img
src={getAssetUrlKey(location.illustration_mobile.id, 'illustration-mobile')}
width={320}
height={824}
alt="Illustration for {location.name}"
decoding="async"
/>
</picture>
{/if}
{#if hasIllustration}
<picture class="location-page__illustration" style:--parallax-y="{illustrationOffsetY}px">
<source media="(min-width: 1200px)" srcset={getAssetUrlKey(location.illustration_desktop_2x.id, 'illustration-desktop-2x')}>
<source media="(min-width: 768px)" srcset={getAssetUrlKey(location.illustration_desktop.id, 'illustration-desktop-1x')}>
<img
src={getAssetUrlKey(location.illustration_mobile.id, 'illustration-mobile')}
width={320}
height={824}
alt="Illustration for {location.name}"
decoding="async"
/>
</picture>
{/if}
</section>
{#if photos.length}
<section class="location-page__houses" bind:this={photosListEl} data-sveltekit-noscroll>
{#each photos as { title, image: { id, title: alt, width, height }, slug, city, date_taken }, index}
<House
{title}
photoId={id}
photoAlt={alt}
url="/{params.country}/{params.location}/{slug}"
{city}
location={location.name}
ratio={width / height}
date={date_taken}
index="{(totalPhotos - index < 10) ? '0' : ''}{totalPhotos - index}"
/>
{/each}
</section>
{#if photos.length}
<section class="location-page__houses" bind:this={photosListEl} data-sveltekit-noscroll>
{#each photos as { title, image: { id, title: alt, width, height }, slug, city, date_taken }, index}
<House
{title}
photoId={id}
photoAlt={alt}
url="/{params.country}/{params.location}/{slug}"
{city}
location={location.name}
ratio={width / height}
date={date_taken}
index="{(totalPhotos - index < 10) ? '0' : ''}{totalPhotos - index}"
/>
{/each}
</section>
<section class="location-page__next container">
<Pagination
ended={ended}
current={currentPhotosAmount}
total={totalPhotos}
on:click={() => !ended && loadMorePhotos()}
>
{#if !ended}
<p class="more">See more photos</p>
{:else}
<p>You've seen it all!</p>
{/if}
</Pagination>
<section class="location-page__next container">
<Pagination
ended={ended}
current={currentPhotosAmount}
total={totalPhotos}
on:click={() => !ended && loadMorePhotos()}
>
{#if !ended}
<p class="more">See more photos</p>
{:else}
<p>You've seen it all!</p>
{/if}
</Pagination>
{#if ended}
<div class="grid-modules">
<div class="container grid">
<div class="wrap">
{#if location.has_poster}
<ShopModule
title="Poster available"
text="Houses of {location.name} is available as a poster on our shop."
images={product.photos_product}
textBottom={null}
buttonText="Buy"
url="/shop/poster-{location.slug}"
/>
{:else}
<ShopModule />
{/if}
<NewsletterModule theme="light" />
</div>
{#if ended}
<div class="grid-modules">
<div class="container grid">
<div class="wrap">
{#if location.has_poster}
<ShopModule
title="Poster available"
text="Houses of {location.name} is available as a poster on our shop."
images={product.photos_product}
textBottom={null}
buttonText="Buy"
url="/shop/poster-{location.slug}"
/>
{:else}
<ShopModule />
{/if}
<NewsletterModule theme="light" />
</div>
</div>
{/if}
</div>
{/if}
{#if location.acknowledgement}
<div class="acknowledgement">
<Image
class="flag"
id={location.country.flag.id}
sizeKey="square-small"
width={32} height={32}
alt="Flag of {location.country.name}"
/>
<p>{location.acknowledgement}</p>
</div>
{/if}
</section>
{:else}
<div class="location-page__message">
<p>
No photos available for {location.name}.<br>
Come back later!
</p>
</div>
{/if}
</main>
</PageTransition>
{#if location.acknowledgement}
<div class="acknowledgement">
<Image
class="flag"
id={location.country.flag.id}
sizeKey="square-small"
width={32} height={32}
alt="Flag of {location.country.name}"
/>
<p>{location.acknowledgement}</p>
</div>
{/if}
</section>
{:else}
<div class="location-page__message">
<p>
No photos available for {location.name}.<br>
Come back later!
</p>
</div>
{/if}
</main>

View File

@@ -19,7 +19,6 @@
// Components
import Metas from '$components/Metas.svelte'
import SplitText from '$components/SplitText.svelte'
import PageTransition from '$components/PageTransition.svelte'
import Image from '$components/atoms/Image.svelte'
import Icon from '$components/atoms/Icon.svelte'
import IconArrow from '$components/atoms/IconArrow.svelte'
@@ -301,105 +300,103 @@
{/if}
<PageTransition>
<main class="photo-page">
<div class="container grid">
<p class="photo-page__notice text-label">Tap for fullscreen</p>
<main class="photo-page">
<div class="container grid">
<p class="photo-page__notice text-label">Tap for fullscreen</p>
<ButtonCircle
tag="a"
url={previousUrl}
color="purple"
class="close shadow-box-dark"
label="Close"
<ButtonCircle
tag="a"
url={previousUrl}
color="purple"
class="close shadow-box-dark"
label="Close"
>
<svg width="12" height="12">
<use xlink:href="#cross">
</svg>
</ButtonCircle>
<div class="photo-page__carousel">
<div class="photo-page__images"
use:swipe
on:swipe={handleSwipe}
on:tap={toggleFullscreen}
>
<svg width="12" height="12">
<use xlink:href="#cross">
</svg>
</ButtonCircle>
<div class="photo-page__carousel">
<div class="photo-page__images"
use:swipe
on:swipe={handleSwipe}
on:tap={toggleFullscreen}
>
{#each visiblePhotos as { id, image, title }, index (id)}
<div class="photo-page__picture is-{currentIndex === 0 ? index + 1 : index}">
<Image
class="photo {image.width / image.height < 1.475 ? 'not-landscape' : ''}"
id={image.id}
alt={title}
sizeKey="photo-list"
sizes={{
small: { width: 500 },
medium: { width: 850 },
large: { width: 1280 },
}}
ratio={1.5}
/>
</div>
{/each}
<div class="photo-page__controls">
<ButtonCircle class="prev shadow-box-dark" label="Previous" disabled={!canGoNext} clone={true} on:click={goToPrevious}>
<IconArrow color="pink" flip={true} />
</ButtonCircle>
<ButtonCircle class="next shadow-box-dark" label="Next" disabled={!canGoPrev} clone={true} on:click={goToNext}>
<IconArrow color="pink" />
</ButtonCircle>
{#each visiblePhotos as { id, image, title }, index (id)}
<div class="photo-page__picture is-{currentIndex === 0 ? index + 1 : index}">
<Image
class="photo {image.width / image.height < 1.475 ? 'not-landscape' : ''}"
id={image.id}
alt={title}
sizeKey="photo-list"
sizes={{
small: { width: 500 },
medium: { width: 850 },
large: { width: 1280 },
}}
ratio={1.5}
/>
</div>
{/each}
<div class="photo-page__index title-index">
<SplitText text="{(currentPhotoIndex < 10) ? '0' : ''}{currentPhotoIndex}" mode="chars" />
</div>
<div class="photo-page__controls">
<ButtonCircle class="prev shadow-box-dark" label="Previous" disabled={!canGoNext} clone={true} on:click={goToPrevious}>
<IconArrow color="pink" flip={true} />
</ButtonCircle>
<ButtonCircle class="next shadow-box-dark" label="Next" disabled={!canGoPrev} clone={true} on:click={goToNext}>
<IconArrow color="pink" />
</ButtonCircle>
</div>
<div class="photo-page__info">
<h1 class="title-medium">{currentPhoto.title}</h1>
<div class="detail text-info">
<a href="/{location.country.slug}/{location.slug}" data-sveltekit-noscroll>
<Icon class="icon" icon="map-pin" label="Map pin" />
<span>
{#if currentPhoto.city}
{currentPhoto.city}, {location.name}, {location.country.name}
{:else}
{location.name}, {location.country.name}
{/if}
</span>
</a>
{#if currentPhoto.date_taken}
<span class="sep">&middot;</span>
<time datetime={dayjs(currentPhoto.date_taken).format('YYYY-MM-DD')}>{dayjs(currentPhoto.date_taken).format('MMMM YYYY')}</time>
{/if}
</div>
<div class="photo-page__index title-index">
<SplitText text="{(currentPhotoIndex < 10) ? '0' : ''}{currentPhotoIndex}" mode="chars" />
</div>
</div>
<div class="photo-page__info">
<h1 class="title-medium">{currentPhoto.title}</h1>
<div class="detail text-info">
<a href="/{location.country.slug}/{location.slug}" data-sveltekit-noscroll>
<Icon class="icon" icon="map-pin" label="Map pin" />
<span>
{#if currentPhoto.city}
{currentPhoto.city}, {location.name}, {location.country.name}
{:else}
{location.name}, {location.country.name}
{/if}
</span>
</a>
{#if currentPhoto.date_taken}
<span class="sep">&middot;</span>
<time datetime={dayjs(currentPhoto.date_taken).format('YYYY-MM-DD')}>{dayjs(currentPhoto.date_taken).format('MMMM YYYY')}</time>
{/if}
</div>
</div>
</div>
</div>
{#if isFullscreen}
<div class="photo-page__fullscreen" bind:this={fullscreenEl}
on:click={toggleFullscreen} on:keydown
in:fade={{ easing: quartOut, duration: 1000 }}
out:fade={{ easing: quartOut, duration: 1000, delay: 300 }}
>
<div class="inner" transition:scale={{ easing: quartOut, start: 1.1, duration: 1000 }}>
<Image
id={currentPhoto.image.id}
sizeKey="photo-grid-large"
width={1266}
height={844}
alt={currentPhoto.title}
/>
<ButtonCircle color="gray-medium" class="close">
<svg width="18" height="18" viewBox="0 0 18 18" fill="#fff" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.751 0c4.274 0 7.752 3.477 7.752 7.751 0 1.846-.65 3.543-1.73 4.875l3.99 3.991a.81.81 0 1 1-1.146 1.146l-3.99-3.991a7.714 7.714 0 0 1-4.876 1.73C3.477 15.503 0 12.027 0 7.753 0 3.476 3.477 0 7.751 0Zm0 1.62a6.138 6.138 0 0 0-6.13 6.131 6.138 6.138 0 0 0 6.13 6.132 6.138 6.138 0 0 0 6.131-6.132c0-3.38-2.75-6.13-6.13-6.13Zm2.38 5.321a.81.81 0 1 1 0 1.62h-4.76a.81.81 0 1 1 0-1.62h4.76Z" />
</svg>
</ButtonCircle>
</div>
{#if isFullscreen}
<div class="photo-page__fullscreen" bind:this={fullscreenEl}
on:click={toggleFullscreen} on:keydown
in:fade={{ easing: quartOut, duration: 1000 }}
out:fade={{ easing: quartOut, duration: 1000, delay: 300 }}
>
<div class="inner" transition:scale={{ easing: quartOut, start: 1.1, duration: 1000 }}>
<Image
id={currentPhoto.image.id}
sizeKey="photo-grid-large"
width={1266}
height={844}
alt={currentPhoto.title}
/>
<ButtonCircle color="gray-medium" class="close">
<svg width="18" height="18" viewBox="0 0 18 18" fill="#fff" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.751 0c4.274 0 7.752 3.477 7.752 7.751 0 1.846-.65 3.543-1.73 4.875l3.99 3.991a.81.81 0 1 1-1.146 1.146l-3.99-3.991a7.714 7.714 0 0 1-4.876 1.73C3.477 15.503 0 12.027 0 7.753 0 3.476 3.477 0 7.751 0Zm0 1.62a6.138 6.138 0 0 0-6.13 6.131 6.138 6.138 0 0 0 6.13 6.132 6.138 6.138 0 0 0 6.131-6.132c0-3.38-2.75-6.13-6.13-6.13Zm2.38 5.321a.81.81 0 1 1 0 1.62h-4.76a.81.81 0 1 1 0-1.62h4.76Z" />
</svg>
</ButtonCircle>
</div>
{/if}
</main>
</PageTransition>
</div>
{/if}
</main>

View File

@@ -16,7 +16,6 @@
import { quartOut } from '$animations/easings'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import Image from '$components/atoms/Image.svelte'
import Button from '$components/atoms/Button.svelte'
import AboutGridPhoto from '$components/atoms/AboutGridPhoto.svelte'
@@ -181,222 +180,220 @@
/>
<PageTransition>
<main class="about">
<Banner
title="About"
image={{
id: '699b4050-6bbf-4a40-be53-d84aca484f9d',
alt: 'Photo caption',
}}
/>
<main class="about">
<Banner
title="About"
image={{
id: '699b4050-6bbf-4a40-be53-d84aca484f9d',
alt: 'Photo caption',
}}
/>
<section class="about__introduction">
<div class="container grid">
<h2 class="title-small">{about.intro_title}</h2>
<div class="heading text-big">
{@html about.intro_heading}
</div>
<div class="text text-small">
{@html about.intro_text}
</div>
<section class="about__introduction">
<div class="container grid">
<h2 class="title-small">{about.intro_title}</h2>
<div class="heading text-big">
{@html about.intro_heading}
</div>
</section>
<section class="about__creation">
<div class="container grid">
<figure class="first-photo">
<Image
class="picture shadow-box-dark"
id={about.intro_firstphoto.id}
alt={about.intro_firstphoto.title}
sizeKey="photo-list"
sizes={{
small: { width: 400 },
medium: { width: 600 },
large: { width: 800 },
}}
ratio={1.5}
/>
<figcaption class="text-info">
{about.intro_firstphoto_caption}<br>
in
<a href="/{about.intro_firstlocation.country.slug}/{about.intro_firstlocation.slug}" data-sveltekit-noscroll>
<img src={getAssetUrlKey(about.intro_firstlocation.country.flag.id, 'square-small-jpg')} width="32" height="32" alt={about.intro_firstlocation.country.flag.title}>
<span>Naarm Australia (Melbourne)</span>
</a>
</figcaption>
</figure>
<h2 class="title-small" data-reveal>{about.creation_title}</h2>
<div class="heading text-huge" data-reveal>
{@html about.creation_heading}
</div>
<div class="text text-small" data-reveal>
{@html about.creation_text}
</div>
<figure class="picture portrait-photo" data-reveal-image>
<Image
class="shadow-box-dark"
id={about.creation_portrait.id}
alt={about.creation_portrait.title}
sizeKey="photo-list"
sizes={{
small: { width: 400 },
medium: { width: 750 },
}}
ratio={1.425}
/>
</figure>
<span class="portrait-photo__caption text-info">
{about.creation_portrait_caption}
</span>
<div class="text text-small">
{@html about.intro_text}
</div>
</section>
</div>
</section>
<section class="about__present">
<div class="container grid">
<figure class="picture" data-reveal-image>
<Image
class="shadow-box-dark"
id={about.present_image.id}
alt={about.present_image.title}
sizeKey="photo-list"
sizes={{
small: { width: 400 },
medium: { width: 600 },
large: { width: 800 },
}}
ratio={1.5}
/>
</figure>
<h2 class="title-small" data-reveal>{about.present_title}</h2>
<div class="text text-small" data-reveal>
<p>{about.present_text}</p>
</div>
<div class="heading text-big" data-reveal>
{@html about.present_heading}
</div>
<div class="conclusion text-small" data-reveal>
<p>{about.present_conclusion}</p>
</div>
</div>
</section>
{#if about.image_showcase}
<div class="about__showcase container grid">
<section class="about__creation">
<div class="container grid">
<figure class="first-photo">
<Image
id={about.image_showcase.id}
alt={about.image_showcase.title}
sizeKey="showcase"
class="picture shadow-box-dark"
id={about.intro_firstphoto.id}
alt={about.intro_firstphoto.title}
sizeKey="photo-list"
sizes={{
small: { width: 400 },
medium: { width: 1000 },
large: { width: 1800 },
medium: { width: 600 },
large: { width: 800 },
}}
ratio={1.2}
ratio={1.5}
/>
<figcaption class="text-info">
{about.intro_firstphoto_caption}<br>
in
<a href="/{about.intro_firstlocation.country.slug}/{about.intro_firstlocation.slug}" data-sveltekit-noscroll>
<img src={getAssetUrlKey(about.intro_firstlocation.country.flag.id, 'square-small-jpg')} width="32" height="32" alt={about.intro_firstlocation.country.flag.title}>
<span>Naarm Australia (Melbourne)</span>
</a>
</figcaption>
</figure>
<h2 class="title-small" data-reveal>{about.creation_title}</h2>
<div class="heading text-huge" data-reveal>
{@html about.creation_heading}
</div>
{/if}
<section class="about__process">
<div class="container grid">
<aside>
<div class="heading">
<h2 class="title-medium">{about.process_title}</h2>
<p class="text-xsmall">{about.process_subtitle}</p>
</div>
<div class="text text-small" data-reveal>
{@html about.creation_text}
</div>
<ol>
{#each about.process_steps as { title }, index}
<li class:is-active={index === currentStep}>
<a href="#step-{index + 1}" class="title-big"
on:click|preventDefault={() => {
currentStep = index
sendEvent('aboutStepSwitch')
<figure class="picture portrait-photo" data-reveal-image>
<Image
class="shadow-box-dark"
id={about.creation_portrait.id}
alt={about.creation_portrait.title}
sizeKey="photo-list"
sizes={{
small: { width: 400 },
medium: { width: 750 },
}}
ratio={1.425}
/>
</figure>
<span class="portrait-photo__caption text-info">
{about.creation_portrait_caption}
</span>
</div>
</section>
<section class="about__present">
<div class="container grid">
<figure class="picture" data-reveal-image>
<Image
class="shadow-box-dark"
id={about.present_image.id}
alt={about.present_image.title}
sizeKey="photo-list"
sizes={{
small: { width: 400 },
medium: { width: 600 },
large: { width: 800 },
}}
ratio={1.5}
/>
</figure>
<h2 class="title-small" data-reveal>{about.present_title}</h2>
<div class="text text-small" data-reveal>
<p>{about.present_text}</p>
</div>
<div class="heading text-big" data-reveal>
{@html about.present_heading}
</div>
<div class="conclusion text-small" data-reveal>
<p>{about.present_conclusion}</p>
</div>
</div>
</section>
{#if about.image_showcase}
<div class="about__showcase container grid">
<Image
id={about.image_showcase.id}
alt={about.image_showcase.title}
sizeKey="showcase"
sizes={{
small: { width: 400 },
medium: { width: 1000 },
large: { width: 1800 },
}}
ratio={1.2}
/>
</div>
{/if}
<section class="about__process">
<div class="container grid">
<aside>
<div class="heading">
<h2 class="title-medium">{about.process_title}</h2>
<p class="text-xsmall">{about.process_subtitle}</p>
</div>
<ol>
{#each about.process_steps as { title }, index}
<li class:is-active={index === currentStep}>
<a href="#step-{index + 1}" class="title-big"
on:click|preventDefault={() => {
currentStep = index
sendEvent('aboutStepSwitch')
}}
>
<span>{title}</span>
</a>
</li>
{/each}
</ol>
</aside>
<div class="steps">
{#each about.process_steps as { text, image, video_mp4, video_webm }, index}
{#if index === currentStep}
<ProcessStep
{index} {text}
image={image ?? undefined}
video={{
mp4: video_mp4?.id,
webm: video_webm?.id
}}
/>
{/if}
{/each}
</div>
</div>
</section>
<section class="about__photos" bind:this={photosGridEl}>
<div class="container-wide">
<div class="photos-grid" style:--parallax-y="{parallaxPhotos}px">
{#each photos as { image: { id }, title }, index}
<AboutGridPhoto class="grid-photo"
{id}
alt={title}
disabled={fadedPhotosIndexes.includes(index)}
/>
{/each}
</div>
</div>
</section>
<section class="about__interest container grid">
<div class="container grid">
<h2 class="title-xl">{about.contact_title}</h2>
<div class="blocks">
{#each about.contact_blocks as { title, text, link, button }}
<div class="block">
<h3 class="text-label">{title}</h3>
<div class="text text-normal">
{@html text}
</div>
<div class="button-container">
{#if link}
{#key emailCopied === link}
<div class="wrap"
in:fly={{ y: 4, duration: 325, easing: quartOutSvelte, delay: 250 }}
out:fade={{ duration: 250, easing: quartOutSvelte }}
use:mailtoClipboard
on:copied={({ detail }) => {
emailCopied = detail.email
// Clear timeout and add timeout to hide message
clearTimeout(emailCopiedTimeout)
emailCopiedTimeout = setTimeout(() => emailCopied = null, 2500)
}}
>
<span>{title}</span>
</a>
</li>
{/each}
</ol>
</aside>
<div class="steps">
{#each about.process_steps as { text, image, video_mp4, video_webm }, index}
{#if index === currentStep}
<ProcessStep
{index} {text}
image={image ?? undefined}
video={{
mp4: video_mp4?.id,
webm: video_webm?.id
}}
/>
{/if}
{/each}
</div>
</div>
</section>
<section class="about__photos" bind:this={photosGridEl}>
<div class="container-wide">
<div class="photos-grid" style:--parallax-y="{parallaxPhotos}px">
{#each photos as { image: { id }, title }, index}
<AboutGridPhoto class="grid-photo"
{id}
alt={title}
disabled={fadedPhotosIndexes.includes(index)}
/>
{/each}
</div>
</div>
</section>
<section class="about__interest container grid">
<div class="container grid">
<h2 class="title-xl">{about.contact_title}</h2>
<div class="blocks">
{#each about.contact_blocks as { title, text, link, button }}
<div class="block">
<h3 class="text-label">{title}</h3>
<div class="text text-normal">
{@html text}
</div>
<div class="button-container">
{#if link}
{#key emailCopied === link}
<div class="wrap"
in:fly={{ y: 4, duration: 325, easing: quartOutSvelte, delay: 250 }}
out:fade={{ duration: 250, easing: quartOutSvelte }}
use:mailtoClipboard
on:copied={({ detail }) => {
emailCopied = detail.email
// Clear timeout and add timeout to hide message
clearTimeout(emailCopiedTimeout)
emailCopiedTimeout = setTimeout(() => emailCopied = null, 2500)
}}
>
{#if emailCopied !== link}
<Button size="small" url="mailto:{link}" text={button} />
{:else}
<span class="clipboard">Email copied in clipboard</span>
{/if}
</div>
{/key}
{/if}
</div>
{#if emailCopied !== link}
<Button size="small" url="mailto:{link}" text={button} />
{:else}
<span class="clipboard">Email copied in clipboard</span>
{/if}
</div>
{/key}
{/if}
</div>
{/each}
</div>
</div>
{/each}
</div>
</section>
</main>
</PageTransition>
</div>
</section>
</main>

View File

@@ -10,7 +10,6 @@
import { quartOut } from 'svelte/easing'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import Image from '$components/atoms/Image.svelte'
import Heading from '$components/molecules/Heading.svelte'
import InteractiveGlobe from '$components/organisms/InteractiveGlobe.svelte'
@@ -66,44 +65,18 @@
/>
<PageTransition>
<main class="credits">
<Heading
text={data.credits.text}
/>
<section class="credits__list">
<div class="grid container">
{#each data.credits.list as { title, credits }}
<div class="credits__category grid">
<h2 class="title-small">{title}</h2>
<ul>
{#each credits as { name, role, website }}
<li>
<dl>
<dt>
{#if website}
<h3>
<a href={website} rel="noopener external" target="_blank" tabindex="0">{name}</a>
</h3>
{:else}
<h3>{name}</h3>
{/if}
</dt>
<dd>
{role}
</dd>
</dl>
</li>
{/each}
</ul>
</div>
{/each}
<main class="credits">
<Heading
text={data.credits.text}
/>
<section class="credits__list">
<div class="grid container">
{#each data.credits.list as { title, credits }}
<div class="credits__category grid">
<h2 class="title-small">Photography</h2>
<h2 class="title-small">{title}</h2>
<ul>
{#each credit as { name, website, location }}
{#each credits as { name, role, website }}
<li>
<dl>
<dt>
@@ -116,33 +89,57 @@
{/if}
</dt>
<dd>
<ul data-sveltekit-noscroll>
{#each location as loc}
{#if loc.location_id}
<li>
<a href="/{loc.location_id.country.slug}/{loc.location_id.slug}" tabindex="0">
<Image
id={loc.location_id.country.flag.id}
sizeKey="square-small"
width={16}
height={16}
alt="Flag of {loc.location_id.country.slug}"
/>
<span>{loc.location_id.name}</span>
</a>
</li>
{/if}
{/each}
</ul>
{role}
</dd>
</dl>
</li>
{/each}
</ul>
</div>
</div>
</section>
{/each}
<InteractiveGlobe type="cropped" />
</main>
</PageTransition>
<div class="credits__category grid">
<h2 class="title-small">Photography</h2>
<ul>
{#each credit as { name, website, location }}
<li>
<dl>
<dt>
{#if website}
<h3>
<a href={website} rel="noopener external" target="_blank" tabindex="0">{name}</a>
</h3>
{:else}
<h3>{name}</h3>
{/if}
</dt>
<dd>
<ul data-sveltekit-noscroll>
{#each location as loc}
{#if loc.location_id}
<li>
<a href="/{loc.location_id.country.slug}/{loc.location_id.slug}" tabindex="0">
<Image
id={loc.location_id.country.flag.id}
sizeKey="square-small"
width={16}
height={16}
alt="Flag of {loc.location_id.country.slug}"
/>
<span>{loc.location_id.name}</span>
</a>
</li>
{/if}
{/each}
</ul>
</dd>
</dl>
</li>
{/each}
</ul>
</div>
</div>
</section>
<InteractiveGlobe type="cropped" />
</main>

View File

@@ -6,7 +6,6 @@
import { getContext } from 'svelte'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import InteractiveGlobe from '$components/organisms/InteractiveGlobe.svelte'
import Locations from '$components/organisms/Locations.svelte'
import ShopModule from '$components/organisms/ShopModule.svelte'
@@ -23,20 +22,18 @@
/>
<PageTransition>
<main class="explore">
<Heading {text} />
<main class="explore">
<Heading {text} />
<section class="explore__locations">
<InteractiveGlobe />
<Locations {locations} />
</section>
<section class="explore__locations">
<InteractiveGlobe />
<Locations {locations} />
</section>
<section class="grid-modules is-spaced grid">
<div class="wrap">
<ShopModule />
<NewsletterModule />
</div>
</section>
</main>
</PageTransition>
<section class="grid-modules is-spaced grid">
<div class="wrap">
<ShopModule />
<NewsletterModule />
</div>
</section>
</main>

View File

@@ -19,7 +19,6 @@
import { PUBLIC_FILTERS_DEFAULT_COUNTRY, PUBLIC_FILTERS_DEFAULT_SORT, PUBLIC_GRID_INCREMENT } from '$env/static/public'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import SplitText from '$components/SplitText.svelte'
import IconEarth from '$components/atoms/IconEarth.svelte'
import Button from '$components/atoms/Button.svelte'
@@ -336,164 +335,162 @@
/>
<PageTransition>
<main class="photos-page">
<section class="photos-page__intro"
class:is-passed={scrolledPastIntro}
<main class="photos-page">
<section class="photos-page__intro"
class:is-passed={scrolledPastIntro}
>
<ScrollingTitle tag="h1" text="Houses">
<SplitText text="Houses" mode="chars" />
</ScrollingTitle>
<DiscoverText />
<div class="filters"
class:is-over={filtersOver}
class:is-transitioning={filtersTransitioning}
class:is-visible={filtersVisible}
>
<ScrollingTitle tag="h1" text="Houses">
<SplitText text="Houses" mode="chars" />
</ScrollingTitle>
<div class="filters__bar">
<span class="text-label filters__label">Filter photos</span>
<ul>
<li>
<Select
name="country" id="filter_country"
options={[
{
value: defaultCountry,
name: 'Worldwide',
default: true,
selected: filterCountry === defaultCountry,
},
...countries.map(({ slug, name }) => ({
value: slug,
name,
selected: filterCountry === slug,
}))
]}
on:change={handleCountryChange}
value={filterCountry}
>
{#if countryFlagId}
<Image
class="icon"
id={countryFlagId}
sizeKey="square-small"
width={26} height={26}
alt="{filterCountry} flag"
/>
{:else}
<IconEarth class="icon" />
{/if}
</Select>
</li>
<li>
<Select
name="sort" id="filter_sort"
options={[
{
value: 'latest',
name: 'Latest',
default: true,
selected: filterSort === defaultSort
},
{
value: 'oldest',
name: 'Oldest',
selected: filterSort === 'oldest'
},
]}
on:change={handleSortChange}
value={filterSort}
>
<svg class="icon" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" aria-label="Sort icon">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.878 15.93h-4.172c-.638 0-1.153.516-1.153 1.154 0 .639.515 1.154 1.153 1.154h4.172c.638 0 1.153-.515 1.153-1.154a1.152 1.152 0 0 0-1.153-1.153Zm3.244-5.396h-7.405c-.639 0-1.154.515-1.154 1.153 0 .639.515 1.154 1.154 1.154h7.405c.639 0 1.154-.515 1.154-1.154a1.145 1.145 0 0 0-1.154-1.153Zm3.244-5.408h-10.65c-.638 0-1.153.515-1.153 1.154 0 .639.515 1.154 1.154 1.154h10.65c.638 0 1.153-.515 1.153-1.154 0-.639-.515-1.154-1.154-1.154ZM7.37 20.679V3.376c0-.145-.03-.289-.082-.433a1.189 1.189 0 0 0-.628-.618 1.197 1.197 0 0 0-.886 0 1.045 1.045 0 0 0-.36.237c-.01 0-.01 0-.021.01L.82 7.145a1.156 1.156 0 0 0 0 1.638 1.156 1.156 0 0 0 1.637 0l2.596-2.596v11.7l-2.596-2.595a1.156 1.156 0 0 0-1.637 0 1.156 1.156 0 0 0 0 1.638l4.573 4.573c.103.103.237.185.37.247.135.062.289.082.433.082h.02c.145 0 .3-.03.433-.093a1.14 1.14 0 0 0 .629-.628.987.987 0 0 0 .092-.432Z" />
</svg>
</Select>
</li>
</ul>
<DiscoverText />
<div class="filters"
class:is-over={filtersOver}
class:is-transitioning={filtersTransitioning}
class:is-visible={filtersVisible}
>
<div class="filters__bar">
<span class="text-label filters__label">Filter photos</span>
<ul>
<li>
<Select
name="country" id="filter_country"
options={[
{
value: defaultCountry,
name: 'Worldwide',
default: true,
selected: filterCountry === defaultCountry,
},
...countries.map(({ slug, name }) => ({
value: slug,
name,
selected: filterCountry === slug,
}))
]}
on:change={handleCountryChange}
value={filterCountry}
>
{#if countryFlagId}
<Image
class="icon"
id={countryFlagId}
sizeKey="square-small"
width={26} height={26}
alt="{filterCountry} flag"
/>
{:else}
<IconEarth class="icon" />
{/if}
</Select>
</li>
<li>
<Select
name="sort" id="filter_sort"
options={[
{
value: 'latest',
name: 'Latest',
default: true,
selected: filterSort === defaultSort
},
{
value: 'oldest',
name: 'Oldest',
selected: filterSort === 'oldest'
},
]}
on:change={handleSortChange}
value={filterSort}
>
<svg class="icon" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" aria-label="Sort icon">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.878 15.93h-4.172c-.638 0-1.153.516-1.153 1.154 0 .639.515 1.154 1.153 1.154h4.172c.638 0 1.153-.515 1.153-1.154a1.152 1.152 0 0 0-1.153-1.153Zm3.244-5.396h-7.405c-.639 0-1.154.515-1.154 1.153 0 .639.515 1.154 1.154 1.154h7.405c.639 0 1.154-.515 1.154-1.154a1.145 1.145 0 0 0-1.154-1.153Zm3.244-5.408h-10.65c-.638 0-1.153.515-1.153 1.154 0 .639.515 1.154 1.154 1.154h10.65c.638 0 1.153-.515 1.153-1.154 0-.639-.515-1.154-1.154-1.154ZM7.37 20.679V3.376c0-.145-.03-.289-.082-.433a1.189 1.189 0 0 0-.628-.618 1.197 1.197 0 0 0-.886 0 1.045 1.045 0 0 0-.36.237c-.01 0-.01 0-.021.01L.82 7.145a1.156 1.156 0 0 0 0 1.638 1.156 1.156 0 0 0 1.637 0l2.596-2.596v11.7l-2.596-2.595a1.156 1.156 0 0 0-1.637 0 1.156 1.156 0 0 0 0 1.638l4.573 4.573c.103.103.237.185.37.247.135.062.289.082.433.082h.02c.145 0 .3-.03.433-.093a1.14 1.14 0 0 0 .629-.628.987.987 0 0 0 .092-.432Z" />
</svg>
</Select>
</li>
</ul>
<div class="filters__actions">
{#if filtered}
<button class="reset button-link"
on:click={resetFiltered}
transition:fly={{ y: 4, duration: 600, easing: quartOutSvelte }}
>
Reset
</button>
{/if}
</div>
<div class="filters__actions">
{#if filtered}
<button class="reset button-link"
on:click={resetFiltered}
transition:fly={{ y: 4, duration: 600, easing: quartOutSvelte }}
>
Reset
</button>
{/if}
</div>
</div>
</section>
</div>
</section>
<section class="photos-page__content" bind:this={photosContentEl} style:--margin-sides="{sideMargins}px">
<div class="grid container">
{#if photos}
<div class="photos-page__grid" bind:this={photosGridEl} data-sveltekit-noscroll>
{#each photos as { id, image, slug, location, title, city }, index (id)}
<figure class="photo shadow-photo">
<a href="/{location.country.slug}/{location.slug}/{slug}" tabindex="0">
<Image
id={image.id}
sizeKey="photo-grid"
sizes={{
small: { width: 500 },
medium: { width: 900 },
large: { width: 1440 },
}}
ratio={1.5}
alt={image.title}
/>
</a>
<figcaption>
<PostCard
street={title}
location={city ? `${city}, ${location.name}` : location.name}
region={location.region}
country={location.country.name}
flagId={location.country.flag.id}
size={isSmall(index) ? 'small' : null}
/>
</figcaption>
</figure>
{/each}
</div>
<section class="photos-page__content" bind:this={photosContentEl} style:--margin-sides="{sideMargins}px">
<div class="grid container">
{#if photos}
<div class="photos-page__grid" bind:this={photosGridEl} data-sveltekit-noscroll>
{#each photos as { id, image, slug, location, title, city }, index (id)}
<figure class="photo shadow-photo">
<a href="/{location.country.slug}/{location.slug}/{slug}" tabindex="0">
<Image
id={image.id}
sizeKey="photo-grid"
sizes={{
small: { width: 500 },
medium: { width: 900 },
large: { width: 1440 },
}}
ratio={1.5}
alt={image.title}
/>
</a>
<figcaption>
<PostCard
street={title}
location={city ? `${city}, ${location.name}` : location.name}
region={location.region}
country={location.country.name}
flagId={location.country.flag.id}
size={isSmall(index) ? 'small' : null}
/>
</figcaption>
</figure>
{/each}
</div>
<div class="controls grid">
<p class="controls__date" title={dayjs(latestPhoto.date_created).format('DD/MM/YYYY, hh:mm')}>
Last updated: <time datetime={dayjs(latestPhoto.date_created).format('YYYY-MM-DD')}>{dayjs().to(dayjs(latestPhoto.date_created))}</time>
</p>
<div class="controls grid">
<p class="controls__date" title={dayjs(latestPhoto.date_created).format('DD/MM/YYYY, hh:mm')}>
Last updated: <time datetime={dayjs(latestPhoto.date_created).format('YYYY-MM-DD')}>{dayjs().to(dayjs(latestPhoto.date_created))}</time>
</p>
<Button
tag="button"
text={!ended ? 'See more photos' : "You've seen it all!"}
size="large" color="beige"
on:click={loadMorePhotos}
disabled={ended}
/>
<Button
tag="button"
text={!ended ? 'See more photos' : "You've seen it all!"}
size="large" color="beige"
on:click={loadMorePhotos}
disabled={ended}
/>
<div class="controls__count">
<span class="current">{currentPhotosAmount}</span>
<span>/</span>
<span class="total">{totalPhotos}</span>
</div>
</div>
{:else if !filteredCountryExists}
<div class="photos-page__message">
<p>
<strong>{$page.url.searchParams.get('country').replace(/(^|\s)\S/g, letter => letter.toUpperCase())}</strong> is not available… yet 👀
</p>
</div>
{/if}
<div class="grid-modules">
<div class="wrap">
<ShopModule />
<NewsletterModule theme="light" />
<div class="controls__count">
<span class="current">{currentPhotosAmount}</span>
<span>/</span>
<span class="total">{totalPhotos}</span>
</div>
</div>
{:else if !filteredCountryExists}
<div class="photos-page__message">
<p>
<strong>{$page.url.searchParams.get('country').replace(/(^|\s)\S/g, letter => letter.toUpperCase())}</strong> is not available… yet 👀
</p>
</div>
{/if}
<div class="grid-modules">
<div class="wrap">
<ShopModule />
<NewsletterModule theme="light" />
</div>
</div>
</section>
</main>
</PageTransition>
</div>
</section>
</main>

View File

@@ -10,7 +10,6 @@
import { quartOut } from '$animations/easings'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import Heading from '$components/molecules/Heading.svelte'
import EmailForm from '$components/molecules/EmailForm.svelte'
import NewsletterIssue from '$components/molecules/NewsletterIssue.svelte'
@@ -65,34 +64,32 @@
/>
<PageTransition>
<main class="subscribe">
<div class="subscribe__top">
<Heading
text={data.newsletter_page_text}
/>
<main class="subscribe">
<div class="subscribe__top">
<Heading
text={data.newsletter_page_text}
/>
<EmailForm />
<EmailForm />
</div>
<section class="subscribe__issues">
<h2 class="title-small">Latest Issue</h2>
<div class="issue-container">
<NewsletterIssue size="large" date={latestIssue.date_sent} {...latestIssue} />
</div>
<section class="subscribe__issues">
<h2 class="title-small">Latest Issue</h2>
<div class="issue-container">
<NewsletterIssue size="large" date={latestIssue.date_sent} {...latestIssue} />
</div>
{#if issues.length > 1}
<h2 class="title-small">Past Issues</h2>
<ul>
{#each issues.slice(1) as { issue, title, date_sent: date, link, thumbnail }}
<li class="issue-container">
<NewsletterIssue {issue} {title} {link} {thumbnail} {date} />
</li>
{/each}
</ul>
{/if}
</section>
{#if issues.length > 1}
<h2 class="title-small">Past Issues</h2>
<ul>
{#each issues.slice(1) as { issue, title, date_sent: date, link, thumbnail }}
<li class="issue-container">
<NewsletterIssue {issue} {title} {link} {thumbnail} {date} />
</li>
{/each}
</ul>
{/if}
</section>
<InteractiveGlobe type="cropped" />
</main>
</PageTransition>
<InteractiveGlobe type="cropped" />
</main>

View File

@@ -6,7 +6,6 @@
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
// Components
import PageTransition from '$components/PageTransition.svelte'
import Metas from '$components/Metas.svelte'
import Heading from '$components/molecules/Heading.svelte'
@@ -22,27 +21,25 @@
/>
<PageTransition>
<main class="terms">
<Heading text="Everything you need to know about using our website or buying our products" />
<main class="terms">
<Heading text="Everything you need to know about using our website or buying our products" />
<section class="terms__categories">
<div class="container grid">
{#each legal.terms as { title, text }, index}
<article class="terms__section grid">
<h2 class="title-small">{index + 1}. {title}</h2>
<div class="text text-info">
{@html text}
</div>
</article>
{/each}
<section class="terms__categories">
<div class="container grid">
{#each legal.terms as { title, text }, index}
<article class="terms__section grid">
<h2 class="title-small">{index + 1}. {title}</h2>
<div class="text text-info">
{@html text}
</div>
</article>
{/each}
<footer>
<p class="text-info">
Updated: <time datetime={dayjs(legal.date_updated).format('YYYY-MM-DD')}>{dayjs().to(dayjs(legal.date_updated))}</time>
</p>
</footer>
</div>
</section>
</main>
</PageTransition>
<footer>
<p class="text-info">
Updated: <time datetime={dayjs(legal.date_updated).format('YYYY-MM-DD')}>{dayjs().to(dayjs(legal.date_updated))}</time>
</p>
</footer>
</div>
</section>
</main>

View File

@@ -7,7 +7,6 @@
import { page } from '$app/stores'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import BoxCTA from '$components/atoms/BoxCTA.svelte'
import Heading from '$components/molecules/Heading.svelte'
import InteractiveGlobe from '$components/organisms/InteractiveGlobe.svelte'
@@ -35,51 +34,49 @@
/>
<PageTransition>
<main class="page-error">
<div class="page-error__top">
<Heading
text="{$page.error.message ?? errors[$page.status].message} <br>{defaultMessage}"
/>
<main class="page-error">
<div class="page-error__top">
<Heading
text="{$page.error.message ?? errors[$page.status].message} <br>{defaultMessage}"
/>
<ListCTAs>
<li>
<BoxCTA
url="/photos"
icon="photos"
label="Browse all photos"
alt="Photos"
/>
</li>
<li>
<BoxCTA
url="/shop"
icon="bag"
label="Shop our products"
alt="Shopping bag"
/>
</li>
<li>
<BoxCTA
url="/about"
icon="compass"
label="Learn about the project"
alt="Compass"
/>
</li>
</ListCTAs>
</div>
<ListCTAs>
<li>
<BoxCTA
url="/photos"
icon="photos"
label="Browse all photos"
alt="Photos"
/>
</li>
<li>
<BoxCTA
url="/shop"
icon="bag"
label="Shop our products"
alt="Shopping bag"
/>
</li>
<li>
<BoxCTA
url="/about"
icon="compass"
label="Learn about the project"
alt="Compass"
/>
</li>
</ListCTAs>
</div>
<InteractiveGlobe />
<Locations {locations} />
<InteractiveGlobe />
<Locations {locations} />
<div class="grid-modules">
<div class="container grid">
<div class="wrap">
<ShopModule />
<NewsletterModule />
</div>
<div class="grid-modules">
<div class="container grid">
<div class="wrap">
<ShopModule />
<NewsletterModule />
</div>
</div>
</main>
</PageTransition>
</div>
</main>

View File

@@ -96,6 +96,7 @@ export const load = async ({ url }) => {
locations: countLocations[0].count.id,
countries: countCountries[0].count.id,
},
currentPath: url.pathname,
}
}
} catch (err) {

View File

@@ -3,10 +3,13 @@
import { browser } from '$app/environment'
import { page } from '$app/stores'
import { beforeNavigate } from '$app/navigation'
import { beforeNavigate, afterNavigate } from '$app/navigation'
import { PUBLIC_ANALYTICS_DOMAIN } from '$env/static/public'
import { onMount, setContext } from 'svelte'
import { setContext, onMount } from 'svelte'
import { fade } from 'svelte/transition'
import { DELAY, DURATION } from '$utils/constants'
import { pageLoading, previousPage } from '$utils/stores'
import { scrollToTop } from 'utils/scroll'
import '$utils/polyfills'
// Components
import SVGSprite from '$components/SVGSprite.svelte'
@@ -37,9 +40,24 @@
/**
* On page change
*/
// Store previous page (for photo Viewer close button)
beforeNavigate(({ from }) => {
beforeNavigate(({ from, to }) => {
// Store previous page (for photo Viewer close button)
$previousPage = from.url.pathname
// Enable page loading state if URL changed
if (from.route.id !== to.route.id) {
$pageLoading = true
}
})
afterNavigate(() => {
// Remove page loading state
setTimeout(() => $pageLoading = false, DELAY.PAGE_LOADING)
// Scroll back to top when new page is ready (excepted certain pages)
if (!$page.url.searchParams.get('country') && !$page.url.pathname.includes('/shop/')) {
setTimeout(scrollToTop, DELAY.PAGE_IN)
}
})
// Define page loading
@@ -65,11 +83,19 @@
<Switcher />
<slot />
{#key data.currentPath}
<div
in:fade={{ duration: DURATION.PAGE_IN, delay: DELAY.PAGE_LOADING }}
out:fade={{ duration: DURATION.PAGE_OUT }}
>
<slot />
{#if !$page.params.photo}
<Footer />
{/if}
</div>
{/key}
{#if !$page.params.photo}
<Footer />
{/if}
<SVGSprite />
<SmoothScroll />

View File

@@ -13,7 +13,6 @@
import { quartOut } from '$animations/easings'
// Components
import Metas from '$components/Metas.svelte'
import PageTransition from '$components/PageTransition.svelte'
import SplitText from '$components/SplitText.svelte'
import Button from '$components/atoms/Button.svelte'
import IconEarth from '$components/atoms/IconEarth.svelte'
@@ -81,89 +80,87 @@
/>
<PageTransition>
<main class="homepage">
<section class="homepage__intro"
use:reveal={{
animation: { opacity: [0, 1] },
options: {
duration: 1,
},
}}
<main class="homepage">
<section class="homepage__intro"
use:reveal={{
animation: { opacity: [0, 1] },
options: {
duration: 1,
},
}}
>
<ScrollingTitle
tag="h1"
class="title-houses"
label="Houses of the World"
offsetStart={-300}
offsetEnd={400}
>
<ScrollingTitle
tag="h1"
class="title-houses"
label="Houses of the World"
offsetStart={-300}
offsetEnd={400}
>
<SplitText text="Houses" mode="chars" />
</ScrollingTitle>
<SplitText text="Houses" mode="chars" />
</ScrollingTitle>
<div class="homepage__headline">
<p class="text-medium">
{settings.description}
</p>
<div class="homepage__headline">
<p class="text-medium">
{settings.description}
</p>
<Button url="#locations" text="Explore locations" on:click={() => $smoothScroll.scrollTo('#locations', { duration: 2 })}>
<IconEarth animate={true} />
</Button>
</div>
</section>
<section class="homepage__photos">
<Collage {photos} />
</section>
<div class="homepage__ctas">
<DiscoverText />
<ListCTAs>
<li>
<BoxCTA
url="/photos"
icon="photos"
label="Browse all photos"
alt="Photos"
/>
</li>
<li>
<BoxCTA
url="/shop"
icon="bag"
label="Shop our products"
alt="Shopping bag"
/>
</li>
<li>
<BoxCTA
url="/about"
icon="compass"
label="Learn about the project"
alt="Compass"
/>
</li>
</ListCTAs>
<Button url="#locations" text="Explore locations" on:click={() => $smoothScroll.scrollTo('#locations', { duration: 2 })}>
<IconEarth animate={true} />
</Button>
</div>
</section>
<section class="homepage__locations" id="locations">
<InteractiveGlobe />
<section class="homepage__photos">
<Collage {photos} />
</section>
<ScrollingTitle tag="p" class="title-world mask">
<SplitText text="World" mode="chars" />
</ScrollingTitle>
<div class="homepage__ctas">
<DiscoverText />
<Locations {locations} />
</section>
<ListCTAs>
<li>
<BoxCTA
url="/photos"
icon="photos"
label="Browse all photos"
alt="Photos"
/>
</li>
<li>
<BoxCTA
url="/shop"
icon="bag"
label="Shop our products"
alt="Shopping bag"
/>
</li>
<li>
<BoxCTA
url="/about"
icon="compass"
label="Learn about the project"
alt="Compass"
/>
</li>
</ListCTAs>
</div>
<div class="grid-modules">
<div class="container grid">
<div class="wrap">
<ShopModule />
<NewsletterModule />
</div>
<section class="homepage__locations" id="locations">
<InteractiveGlobe />
<ScrollingTitle tag="p" class="title-world mask">
<SplitText text="World" mode="chars" />
</ScrollingTitle>
<Locations {locations} />
</section>
<div class="grid-modules">
<div class="container grid">
<div class="wrap">
<ShopModule />
<NewsletterModule />
</div>
</div>
</main>
</PageTransition>
</div>
</main>