🚧 Use PageTransition as a div and switch
- use a page classed div for PageTransition which avoids to make global style for the page - fix the loading spinner that was too short and would come and go before arriving on the page, now fades out when changing page as pageLoading is defined on the PageTransition afterUpdate
This commit is contained in:
@@ -34,49 +34,51 @@
|
||||
title="{errors[$page.status].title} – Houses Of"
|
||||
/>
|
||||
|
||||
<PageTransition name="page-error">
|
||||
<div class="page-error__top">
|
||||
<Heading
|
||||
text="{$page.error.message ?? errors[$page.status].message} <br>{defaultMessage}"
|
||||
/>
|
||||
<PageTransition>
|
||||
<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 class="grid-modules">
|
||||
<div class="container grid">
|
||||
<div class="wrap">
|
||||
<ShopModule />
|
||||
<NewsletterModule />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -7,7 +7,6 @@
|
||||
import type { PageData } from './$types'
|
||||
import { onMount, setContext } from 'svelte'
|
||||
import { pageLoading, previousPage } from '$utils/stores'
|
||||
import { DURATION } from '$utils/contants'
|
||||
import '$utils/polyfills'
|
||||
import { PUBLIC_ANALYTICS_KEY, PUBLIC_ANALYTICS_URL } from '$env/static/public'
|
||||
// Components
|
||||
@@ -46,14 +45,7 @@
|
||||
|
||||
// Define page loading from navigating store
|
||||
navigating.subscribe((store: any) => {
|
||||
if (store) {
|
||||
$pageLoading = true
|
||||
|
||||
// Turn page loading when changing page
|
||||
setTimeout(() => {
|
||||
$pageLoading = false
|
||||
}, DURATION.PAGE_IN * 1.25)
|
||||
}
|
||||
store && ($pageLoading = true)
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
|
||||
@@ -82,87 +82,89 @@
|
||||
/>
|
||||
<!-- image={getAssetUrlKey(settings.seo_image.id, 'share-image')} -->
|
||||
|
||||
<PageTransition name="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}
|
||||
<PageTransition>
|
||||
<main class="homepage">
|
||||
<section class="homepage__intro"
|
||||
use:reveal={{
|
||||
animation: { opacity: [0, 1] },
|
||||
options: {
|
||||
duration: 1,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SplitText text="Houses" mode="chars" />
|
||||
</ScrollingTitle>
|
||||
<ScrollingTitle
|
||||
tag="h1"
|
||||
class="title-houses"
|
||||
label="Houses of the World"
|
||||
offsetStart={-300}
|
||||
offsetEnd={400}
|
||||
>
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="homepage__photos">
|
||||
<Collage {photos} />
|
||||
</section>
|
||||
<section class="homepage__locations" id="locations">
|
||||
<InteractiveGlobe />
|
||||
|
||||
<div class="homepage__ctas">
|
||||
<DiscoverText />
|
||||
<ScrollingTitle tag="p" class="title-world mask">
|
||||
<SplitText text="World" mode="chars" />
|
||||
</ScrollingTitle>
|
||||
|
||||
<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>
|
||||
<Locations {locations} />
|
||||
</section>
|
||||
|
||||
<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 class="grid-modules">
|
||||
<div class="container grid">
|
||||
<div class="wrap">
|
||||
<ShopModule />
|
||||
<NewsletterModule />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -218,148 +218,149 @@
|
||||
|
||||
<svelte:window bind:scrollY />
|
||||
|
||||
<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>
|
||||
|
||||
<PageTransition name="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}
|
||||
</p>
|
||||
{#if latestPhoto}
|
||||
·
|
||||
<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>
|
||||
<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}
|
||||
</div>
|
||||
{#if latestPhoto}
|
||||
·
|
||||
<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>
|
||||
|
||||
<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 /> -->
|
||||
<div class="ctas">
|
||||
<Button url="/locations" text="Change location" class="shadow-small">
|
||||
<IconEarth />
|
||||
</Button>
|
||||
{/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}
|
||||
</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>
|
||||
|
||||
{#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 location.has_poster}
|
||||
<Button url="/shop/poster-{location.slug}" text="Buy the poster" color="pinklight" class="shadow-small">
|
||||
<!-- <IconEarth /> -->
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#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}"
|
||||
{#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"
|
||||
/>
|
||||
<p>{location.acknowledgement}</p>
|
||||
</div>
|
||||
</picture>
|
||||
{/if}
|
||||
</section>
|
||||
{:else}
|
||||
<div class="location-page__message">
|
||||
<p>
|
||||
No photos available for {location.name}.<br>
|
||||
Come back later!
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#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>
|
||||
|
||||
{#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>
|
||||
</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>
|
||||
@@ -305,98 +305,100 @@
|
||||
{/if}
|
||||
|
||||
|
||||
<PageTransition name="photo-page">
|
||||
<div class="container grid">
|
||||
<p class="photo-page__notice text-label">Tap for fullscreen</p>
|
||||
<PageTransition>
|
||||
<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"
|
||||
>
|
||||
<svg width="12" height="12">
|
||||
<use xlink:href="#cross">
|
||||
</svg>
|
||||
</ButtonCircle>
|
||||
<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}>
|
||||
{#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 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>
|
||||
</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>
|
||||
|
||||
<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="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-prefetch 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">·</span>
|
||||
<time datetime={dayjs(currentPhoto.date_taken).format('YYYY-MM-DD')}>{dayjs(currentPhoto.date_taken).format('MMMM YYYY')}</time>
|
||||
{/if}
|
||||
<div class="detail text-info">
|
||||
<a href="/{location.country.slug}/{location.slug}" data-sveltekit-prefetch 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">·</span>
|
||||
<time datetime={dayjs(currentPhoto.date_taken).format('YYYY-MM-DD')}>{dayjs(currentPhoto.date_taken).format('MMMM YYYY')}</time>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if isFullscreen}
|
||||
<div class="photo-page__fullscreen" bind:this={fullscreenEl} on:click={toggleFullscreen}
|
||||
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>
|
||||
{#if isFullscreen}
|
||||
<div class="photo-page__fullscreen" bind:this={fullscreenEl} on:click={toggleFullscreen}
|
||||
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>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -180,215 +180,216 @@
|
||||
image={about.seo_image ? getAssetUrlKey(about.seo_image.id, 'share-image') : null}
|
||||
/>
|
||||
|
||||
<PageTransition>
|
||||
<main class="about">
|
||||
<Banner
|
||||
title="About"
|
||||
image={{
|
||||
id: '699b4050-6bbf-4a40-be53-d84aca484f9d',
|
||||
alt: 'Photo caption',
|
||||
}}
|
||||
/>
|
||||
|
||||
<PageTransition name="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>
|
||||
</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 data-sveltekit-prefetch>
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
|
||||
<ol>
|
||||
{#each about.process_steps as { title }, index}
|
||||
<li class:is-active={index === currentStep}>
|
||||
<a href="#step-{index + 1}" class="title-big">
|
||||
<span>{title}</span>
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
</aside>
|
||||
|
||||
<div class="steps">
|
||||
{#each about.process_steps as { text, image, video_mp4, video_webm }, index}
|
||||
<ProcessStep
|
||||
{index} {text}
|
||||
image={image ?? undefined}
|
||||
video={video_mp4 && video_webm ? {
|
||||
mp4: video_mp4.id,
|
||||
webm: video_webm.id
|
||||
} : undefined}
|
||||
visible={index === currentStep}
|
||||
/>
|
||||
{/each}
|
||||
<div class="text text-small">
|
||||
{@html about.intro_text}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</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)}
|
||||
<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}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<figcaption class="text-info">
|
||||
{about.intro_firstphoto_caption}<br>
|
||||
in
|
||||
<a href="/{about.intro_firstlocation.country.slug}/{about.intro_firstlocation.slug}" data-sveltekit-noscroll data-sveltekit-prefetch>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
</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>
|
||||
{/each}
|
||||
|
||||
<ol>
|
||||
{#each about.process_steps as { title }, index}
|
||||
<li class:is-active={index === currentStep}>
|
||||
<a href="#step-{index + 1}" class="title-big">
|
||||
<span>{title}</span>
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
</aside>
|
||||
|
||||
<div class="steps">
|
||||
{#each about.process_steps as { text, image, video_mp4, video_webm }, index}
|
||||
<ProcessStep
|
||||
{index} {text}
|
||||
image={image ?? undefined}
|
||||
video={video_mp4 && video_webm ? {
|
||||
mp4: video_mp4.id,
|
||||
webm: video_webm.id
|
||||
} : undefined}
|
||||
visible={index === currentStep}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</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>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -17,7 +17,7 @@
|
||||
import InteractiveGlobe from '$components/organisms/InteractiveGlobe.svelte'
|
||||
|
||||
export let data: PageData
|
||||
const { credits, credit } = data
|
||||
const { credit } = data
|
||||
|
||||
|
||||
onMount(() => {
|
||||
@@ -63,22 +63,47 @@
|
||||
|
||||
<Metas
|
||||
title="Credits – Houses Of"
|
||||
description={credits.text}
|
||||
description={data.credits.text}
|
||||
/>
|
||||
|
||||
<PageTransition>
|
||||
<main class="credits">
|
||||
<Heading
|
||||
text={data.credits.text}
|
||||
/>
|
||||
|
||||
<PageTransition name="credits">
|
||||
<Heading
|
||||
text={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}
|
||||
|
||||
<section class="credits__list">
|
||||
<div class="grid container">
|
||||
{#each credits.list as { title, credits }}
|
||||
<div class="credits__category grid">
|
||||
<h2 class="title-small">{title}</h2>
|
||||
<h2 class="title-small">Photography</h2>
|
||||
<ul>
|
||||
{#each credits as { name, role, website }}
|
||||
{#each credit as { name, website, location }}
|
||||
<li>
|
||||
<dl>
|
||||
<dt>
|
||||
@@ -91,57 +116,33 @@
|
||||
{/if}
|
||||
</dt>
|
||||
<dd>
|
||||
{role}
|
||||
<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>
|
||||
{/each}
|
||||
|
||||
<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>
|
||||
</section>
|
||||
|
||||
<InteractiveGlobe type="cropped" />
|
||||
<InteractiveGlobe type="cropped" />
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -23,18 +23,20 @@
|
||||
image=""
|
||||
/>
|
||||
|
||||
<PageTransition name="explore">
|
||||
<Heading {text} />
|
||||
<PageTransition>
|
||||
<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>
|
||||
<section class="grid-modules is-spaced grid">
|
||||
<div class="wrap">
|
||||
<ShopModule />
|
||||
<NewsletterModule />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -336,162 +336,164 @@
|
||||
/>
|
||||
|
||||
|
||||
<PageTransition name="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}
|
||||
<PageTransition>
|
||||
<main class="photos-page">
|
||||
<section class="photos-page__intro"
|
||||
class:is-passed={scrolledPastIntro}
|
||||
>
|
||||
<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>
|
||||
<ScrollingTitle tag="h1" text="Houses">
|
||||
<SplitText text="Houses" mode="chars" />
|
||||
</ScrollingTitle>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
</section>
|
||||
<DiscoverText />
|
||||
|
||||
<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 data-sveltekit-prefetch>
|
||||
{#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="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="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}
|
||||
/>
|
||||
|
||||
<div class="controls__count">
|
||||
<span class="current">{currentPhotosAmount}</span>
|
||||
<span>/</span>
|
||||
<span class="total">{totalPhotos}</span>
|
||||
<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>
|
||||
{: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>
|
||||
</section>
|
||||
|
||||
<div class="grid-modules">
|
||||
<div class="wrap">
|
||||
<ShopModule />
|
||||
<NewsletterModule theme="light" />
|
||||
<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 data-sveltekit-prefetch>
|
||||
{#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>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -25,17 +25,19 @@
|
||||
/>
|
||||
|
||||
|
||||
<PageTransition name="shop-page">
|
||||
<ShopHeader />
|
||||
<PageTransition>
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<PostersGrid {posters} />
|
||||
<PostersGrid {posters} />
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -26,13 +26,15 @@
|
||||
/>
|
||||
|
||||
|
||||
<PageTransition name="shop-page">
|
||||
<ShopHeader {product} />
|
||||
<PageTransition>
|
||||
<main class="shop-page">
|
||||
<ShopHeader {product} />
|
||||
|
||||
<PosterLayout
|
||||
product={product}
|
||||
shopProduct={shopProduct}
|
||||
/>
|
||||
<PosterLayout
|
||||
product={product}
|
||||
shopProduct={shopProduct}
|
||||
/>
|
||||
|
||||
<PostersGrid {posters} />
|
||||
<PostersGrid {posters} />
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -24,13 +24,15 @@
|
||||
/>
|
||||
|
||||
|
||||
<PageTransition name="shop-page">
|
||||
<ShopHeader product={data.product} />
|
||||
<PageTransition>
|
||||
<main class="shop-page">
|
||||
<ShopHeader product={data.product} />
|
||||
|
||||
<PosterLayout
|
||||
product={data.product}
|
||||
shopProduct={data.shopProduct}
|
||||
/>
|
||||
<PosterLayout
|
||||
product={data.product}
|
||||
shopProduct={data.shopProduct}
|
||||
/>
|
||||
|
||||
<PostersGrid {posters} />
|
||||
<PostersGrid {posters} />
|
||||
</main>
|
||||
</PageTransition>
|
||||
@@ -65,32 +65,34 @@
|
||||
description="Subscribe to the Houses Of newsletter to be notified when new photos or locations are added to the site and when more prints are available on our shop"
|
||||
/>
|
||||
|
||||
<PageTransition name="subscribe">
|
||||
<div class="subscribe__top">
|
||||
<Heading
|
||||
text={data.newsletter_page_text}
|
||||
/>
|
||||
<PageTransition>
|
||||
<main class="subscribe">
|
||||
<div class="subscribe__top">
|
||||
<Heading
|
||||
text={data.newsletter_page_text}
|
||||
/>
|
||||
|
||||
<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} />
|
||||
<EmailForm />
|
||||
</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>
|
||||
<section class="subscribe__issues">
|
||||
<h2 class="title-small">Latest Issue</h2>
|
||||
<div class="issue-container">
|
||||
<NewsletterIssue size="large" date={latestIssue.date_sent} {...latestIssue} />
|
||||
</div>
|
||||
|
||||
<InteractiveGlobe type="cropped" />
|
||||
{#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>
|
||||
@@ -23,25 +23,27 @@
|
||||
/>
|
||||
|
||||
|
||||
<PageTransition name="terms">
|
||||
<Heading text="Everything you need to know about using our website or buying our products" />
|
||||
<PageTransition>
|
||||
<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>
|
||||
<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>
|
||||
Reference in New Issue
Block a user