[wip] Rework About page

This commit is contained in:
2022-09-07 23:59:49 +02:00
parent e9fa0d3532
commit 28ed5c4f94
7 changed files with 802 additions and 598 deletions

View File

@@ -0,0 +1,98 @@
<style lang="scss">
@import "../../style/organisms/banner";
</style>
<script lang="ts">
import { navigating } from '$app/stores'
import { onMount } from 'svelte'
import { stagger, timeline } from 'motion'
import { DELAY } from '$utils/contants'
import { quartOut } from '$animations/easings'
// Components
import Image from '$components/atoms/Image.svelte'
export let type: string = undefined
export let title: string
export let image: any
onMount(() => {
/**
* Animations
*/
// const animation = timeline([
// // Hero image
// ['.shop-page__background', {
// scale: [1.06, 1],
// opacity: [0, 1],
// }, {
// at: 0.4,
// duration: 2.4,
// }],
// // Intro top elements
// ['.shop-page__intro .top > *', {
// y: [-100, 0],
// opacity: [0, 1],
// }, {
// at: 0.4,
// delay: stagger(0.25),
// }],
// // Hero title
// ['.shop-page__title h1', {
// y: [32, 0],
// opacity: [0, 1],
// }, {
// at: 0.5,
// }],
// // Intro navbar
// ['.shop-page__nav .container > *, .shop-page__intro .button-cart', {
// y: [100, 0],
// opacity: [0, 1],
// }, {
// at: 0.7,
// delay: stagger(0.25),
// }]
// ], {
// delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
// defaultOptions: {
// duration: 1.6,
// easing: quartOut,
// },
// })
// animation.stop()
// // Run animation
// requestAnimationFrame(animation.play)
})
</script>
<section class="banner">
<div class="banner__top container">
<a href="/" class="back" data-sveltekit-noscroll>
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 1 1 4l3 3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span>Back to Houses Of</span>
</a>
</div>
<div class="banner__title">
<h1>{title}</h1>
</div>
<Image
class="banner__background"
id={image.id}
alt={image.alt}
sizeKey="hero"
sizes={{
large: { width: 1800, height: 1200 },
medium: { width: 1200, height: 800 },
small: { width: 700, height: 700 },
}}
lazy={false}
/>
</section>

View File

@@ -19,17 +19,14 @@
import AboutGridPhoto from '$components/atoms/AboutGridPhoto.svelte'
import Heading from '$components/molecules/Heading.svelte'
import ProcessStep from '$components/molecules/ProcessStep.svelte'
import InteractiveGlobe2 from '$components/organisms/InteractiveGlobe2.svelte'
import ShopModule from '$components/organisms/ShopModule.svelte'
import NewsletterModule from '$components/organisms/NewsletterModule.svelte'
import Banner from '$components/organisms/Banner.svelte'
export let data: PageData
const { about, photos } = data
let scrollY: number, innerWidth: number, innerHeight: number
let purposeEl: HTMLElement, photosGridEl: HTMLElement
let photosGridEl: HTMLElement
let currentStep: number = 0
let photoFirstEl: HTMLElement, photoUsEl: HTMLElement
let photosGridOffset: number = photosGridEl && photosGridEl.offsetTop
$: currentStep = $page.url.hash ? Number($page.url.hash.split('#step-')[1]) - 1 : 0
@@ -51,150 +48,62 @@
/**
* Animations
*/
const animation = timeline([
// Heading
['.heading .text', {
y: [24, 0],
opacity: [0, 1],
z: 0,
}, {
at: 0.5,
}],
// const animation = timeline([
// // Heading
// ['.heading .text', {
// y: [24, 0],
// opacity: [0, 1],
// z: 0,
// }, {
// at: 0.5,
// }],
// First photo
[photoFirstEl, {
y: ['10%', 0],
rotate: [0, getComputedStyle(photoFirstEl).getPropertyValue('--rotate')],
opacity: [0, 1],
z: 0,
}, {
at: 0.75,
opacity: {
duration: 1
}
}],
// // First photo
// [photoFirstEl, {
// y: ['10%', 0],
// rotate: [0, getComputedStyle(photoFirstEl).getPropertyValue('--rotate')],
// opacity: [0, 1],
// z: 0,
// }, {
// at: 0.75,
// opacity: {
// duration: 1
// }
// }],
// Portrait photo
[photoUsEl, {
y: ['10%', 0],
x: [0, '5%'],
rotate: [0, 5],
opacity: [0, 1],
z: 0,
}, {
at: 1,
opacity: {
duration: 1
}
}],
// // Portrait photo
// [photoUsEl, {
// y: ['10%', 0],
// x: [0, '5%'],
// rotate: [0, 5],
// opacity: [0, 1],
// z: 0,
// }, {
// at: 1,
// opacity: {
// duration: 1
// }
// }],
// Text
['.about__introduction .text', {
y: [32, 0],
opacity: [0, 1],
z: 0,
}, {
at: 1.2,
}],
], {
delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
defaultOptions: {
duration: 1.6,
easing: quartOut,
},
})
animation.stop()
// // Text
// ['.about__introduction .text', {
// y: [32, 0],
// opacity: [0, 1],
// z: 0,
// }, {
// at: 1.2,
// }],
// ], {
// delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
// defaultOptions: {
// duration: 1.6,
// easing: quartOut,
// },
// })
// animation.stop()
// Run animation
requestAnimationFrame(animation.play)
/**
* Intro parallax
*/
// First photo
scroll(animate(photoFirstEl.querySelector('figure'), {
y: ['-3%', '6%'],
x: [0, '-4%'],
rotate: [-1.5, 0],
z: 0,
}), {
target: photoFirstEl,
offset: ["-200%", "150%"]
})
// Portrait photo
scroll(animate(photoUsEl.querySelector('figure'), {
y: [0, '-6%'],
x: [0, '-3%'],
rotate: [-2, 0],
z: 0,
}), {
target: photoUsEl,
offset: ["-250%", "150%"]
})
/**
* Purpose reveal
*/
inView(purposeEl, ({ target, isIntersecting }) => {
target.classList.toggle('is-visible', isIntersecting)
}, { amount: 0.6 })
// Parallax
scroll(animate(purposeEl.querySelector('picture img'), {
y: [0, '40%'],
}))
/**
* Steps scroll animation
*/
const cards = stepsEl.querySelectorAll('.step')
const cardsAmount = about.process_steps.length
cards.forEach((card: HTMLElement, i: number) => {
const index = i + 1
const reverseIndex = cardsAmount - index
const overlay = card.querySelector('.overlay')
const scrollOptions: ScrollOptions = {
target: stepsEl,
offset: [`${i / cardsAmount * 100}%`, `${index / cardsAmount * 100}%`],
}
// Card scale
scroll(animate(card, {
scale: [1, 1 - (0.02 * reverseIndex)]
}), scrollOptions)
// Overlay opacity
scroll(animate(overlay, {
opacity: [0, 0.2 + (0.05 * reverseIndex)]
}), scrollOptions)
})
/**
* Play videos only when visible
*/
const videos = stepsEl.querySelectorAll('video')
if (videos) {
videosObserver = new IntersectionObserver(entries => {
entries.forEach(({ target, isIntersecting }) => {
// @ts-ignore
isIntersecting ? target.play() : target.pause()
})
}, {
threshold: 0,
})
videos.forEach(video => videosObserver.observe(video))
}
// Destroy
return () => {
videosObserver.disconnect()
}
// // Run animation
// requestAnimationFrame(animation.play)
})
@@ -214,72 +123,51 @@
<PageTransition name="about">
<Heading
text={about.description}
<Banner
title="About"
image={{
id: '699b4050-6bbf-4a40-be53-d84aca484f9d',
alt: 'Photo caption',
}}
/>
<section class="about__introduction">
<div class="container grid">
<div class="photo-first" bind:this={photoFirstEl}>
<figure>
<Image
class="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}</figcaption>
</figure>
</div>
<h2 class="title-small">Meet the makers</h2>
<p class="heading text-big">We are a French and Australian couple that found each other through our mutual <strong>passion for travel, photography and design</strong>.</p>
<div class="photo-us" bind:this={photoUsEl}>
<figure>
<Image
class="shadow-box-dark"
id={about.intro_portraits.id}
alt={about.intro_portraits.title}
sizeKey="square"
sizes={{
small: { width: 250 }
}}
ratio={1}
/>
</figure>
</div>
<div class="text text-normal">
{@html introText}
<div class="text text-small">
<p>With a strong desire to create, were award winning in our own fields with <a href="">Félix</a> as a Digital Designer and Art Director and <a href="">Shelby</a> as a Front-End Developer.</p>
</div>
</div>
</section>
<section class="about__purpose grid" bind:this={purposeEl}>
<div class="container">
<div class="text title-xl">
{@html about.purpose_text}
</div>
<div class="background">
<picture class="background__illustration">
<source media="(min-width: 1200px)" srcset={getAssetUrlKey(about.intro_firstlocation.illustration_desktop_2x.id, 'illustration-desktop-2x')}>
<source media="(min-width: 768px)" srcset={getAssetUrlKey(about.intro_firstlocation.illustration_desktop.id, 'illustration-desktop-1x')}>
<img
src={getAssetUrlKey(about.intro_firstlocation.illustration_mobile.id, 'illustration-mobile')}
width={320}
height={824}
alt="Illustration for {about.intro_firstlocation.name}"
decoding="async"
/>
</picture>
</div>
<div class="about__creation">
<div class="container grid">
<figure class="first-photo">
<Image
class="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>
</div>
</section>
</div>
<section class="about__process">
<div class="container grid">

View File

@@ -97,6 +97,20 @@
/* ==========================================================================
TEXT
========================================================================== */
// Big
.text-big {
font-size: rem(32px);
font-weight: 300;
line-height: 1.3;
@include bp (sm) {
font-size: rem(36px);
}
@include bp (sd) {
font-size: rem(44px);
}
}
// Large
.text-large {
font-size: rem(32px);

View File

@@ -0,0 +1,111 @@
.banner {
position: relative;
z-index: 30;
height: 24vw;
min-height: 200px;
overflow: hidden;
@include bp (lg) {
max-height: 400px;
min-height: 275px;
}
// title
&__title {
position: absolute;
z-index: 2;
top: 50%;
left: 50%;
width: 100%;
transform: translate3d(-50%, -50%, 0);
@include bp (sm) {
// top: 50%;
// left: 0;
// transform: none;
}
h1 {
font-size: clamp(#{rem(48px)}, 7vw, #{rem(56px)});
font-weight: 400;
text-shadow: 0px 8px 12px rgba(#000, 0.25);
text-align: center;
letter-spacing: -0.02em;
:global(span), :global(strong) {
color: #fff;
}
:global(span) {
font-weight: 300;
}
}
}
// Top
&__top {
position: absolute;
z-index: 1;
top: 20px;
left: 0;
padding: 0 20px;
display: flex;
justify-content: space-between;
width: 100%;
margin: 0 auto;
@include bp (sm) {
top: 32px;
padding: 0 32px;
}
// Back
.back {
display: flex;
align-items: center;
color: #fff;
font-size: rem(14px);
color: $color-cream;
text-decoration: none;
transition: color 0.4s var(--ease-quart);
@include bp (sm) {
max-width: none;
font-size: rem(18px);
}
svg {
margin-right: 8px;
transition: transform 0.4s var(--ease-quart);
}
// Hover
&:hover {
color: $color-tertiary;
svg {
transform: translate3d(-4px, 0, 0);
}
}
}
}
// Background Image
:global(picture) {
position: relative;
display: flex;
align-items: flex-end;
width: 100%;
height: 100%;
background-color: $color-primary-darker;
pointer-events: none;
user-select: none;
:global(img) {
opacity: 0.55;
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
}
}

View File

@@ -3,247 +3,119 @@
** Introduction
*/
&__introduction {
:global(picture) {
overflow: hidden;
padding: clamp(48px, 10vw, 80px) 0;
:global(img) {
display: block;
width: 100%;
height: auto;
}
@include bp (sm) {
padding: clamp(80px, 7vw, 128px) 0 clamp(200px, 20vw, 360px);
}
// First photo
.photo-first {
--rotate: -3deg;
$offset: 32px;
grid-column: 1 / -2;
grid-row: 1;
margin-left: -$offset;
transform: rotate(var(--rotate)) translateZ(0);
// Section title
h2 {
@include bp (sm) {
grid-column: 2 / -6;
}
@include bp (md) {
grid-column: 4 / span 12;
margin-left: 0;
}
:global(picture) {
border-radius: clamp(8px, 1vw, 16px);
}
figcaption {
width: 75%;
max-width: 250px;
margin-top: 12px;
margin-left: $offset;
color: rgba($color-tertiary, 0.5);
@include bp (mob-lg) {
max-width: 400px;
}
@include bp (sm) {
width: 100%;
max-width: none;
margin-left: 0;
}
grid-column: 3 / span 12;
grid-row: 1;
margin-bottom: 24px;
}
}
// Portrait
.photo-us {
position: relative;
grid-row: 1;
z-index: 2;
grid-column: 6 / -1;
margin-top: clamp(56px, 12vw, 120px);
// Heading text
.heading {
@include bp (sm) {
grid-column: 18 / -1;
}
@include bp (md) {
grid-column: 16 / span 4;
margin-top: clamp(56px, 7vw, 112px);
grid-column: 3 / span 12;
grid-row: 2;
align-self: baseline;
max-width: 788px;
}
:global(picture) {
overflow: hidden;
border-radius: clamp(6px, 1vw, 12px);
transform: translate3d(clamp(32px, 3vw, 56px), 0, 0);
@include bp (md) {
transform: translate3d(calc(-1 * clamp(32px, 3vw, 56px)), 0, 0);
}
strong {
color: $color-secondary-light;
font-weight: inherit;
}
}
// Text
// Right text
.text {
grid-column: 1 / -1;
grid-row: 3;
color: $color-tertiary;
margin-top: 48px;
@include bp (sm) {
margin-top: 96px;
grid-column: 3 / -3;
}
@include bp (md) {
grid-column: 17 / span 7;
// max-width: 420px;
margin-top: calc(-1 * clamp(80px, 8vw, 120px));
grid-column: 17 / span 6;
grid-row: 2;
align-self: baseline;
}
:global(img) {
display: inline-block;
width: 20px;
height: auto;
margin-right: 4px;
margin-left: 8px;
margin-bottom: 3px;
border-radius: 100%;
}
:global(a) {
display: inline-block;
a {
color: currentColor;
text-decoration: none;
transition: color 0.3s;
&:hover {
:global(strong) {
color: $color-secondary-light;
}
color: $color-secondary-light;
}
}
:global(strong) {
font-weight: normal;
padding-bottom: 2px;
background-image: linear-gradient(rgba($color-tertiary, 0.3), rgba($color-tertiary, 0.3));
background-position: 0 100%;
background-size: 100% 1px;
background-repeat: no-repeat;
transition: color 0.4s var(--ease-quart);
}
}
}
/*
** Purpose
** Creation
*/
&__purpose {
margin-top: 72px;
text-align: center;
&__creation {
background: #fff;
@include bp (sm) {
margin-top: 120px;
}
.container {
grid-column: 2 / -2;
position: relative;
// First photo
.first-photo {
display: flex;
align-items: center;
justify-content: center;
height: calc(var(--vh) * 0.9);
max-height: 720px;
color: #fff;
padding: 0 8%;
flex-direction: column;
@include bp (sm) {
padding: 0 18%;
max-height: 1200px;
}
}
// Text
.text {
opacity: 0.2;
max-width: 1024px;
transition: opacity 3s var(--ease-quart);
:global(strong) {
font-weight: inherit;
transition: color 3s var(--ease-quart);
}
}
// Background
.background {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
opacity: 0;
background-color: $color-primary-tertiary20;
border-radius: 0px;
transform: scale(1.15) translateZ(0);
transition-property: opacity, transform, border-radius;
transition-delay: 0.25s;
&, &__illustration img {
transition-duration: 2.5s;
transition-timing-function: var(--ease-quart);
grid-column: 8 / -2;
margin: -10vw 0 clamp(80px, 10vw, 128px);
}
// Illustration
&__illustration {
position: relative;
:global(picture) {
width: 100%;
height: 100%;
opacity: 0.75;
$mask: linear-gradient(180deg, #000 0%, rgba(0,0,0,0) 62.5%);
-webkit-mask-image: $mask;
mask-image: $mask;
user-select: none;
pointer-events: none;
border-radius: 16px;
overflow: hidden;
img {
position: absolute;
bottom: 60%;
left: 0;
:global(img) {
display: block;
width: 100%;
height: auto;
opacity: 0;
transition-property: opacity;
transition-delay: 0.6s;
@include bp (md) {
bottom: 50%;
}
@include bp (sd) {
bottom: 40%;
}
}
}
}
// Visible state
&:global(.is-visible) {
.text {
opacity: 1;
:global(strong) {
color: darken($color-secondary-light, 4);
}
}
.background {
opacity: 1;
transform: scale(1) translateZ(0);
border-radius: 8px;
figcaption {
margin-left: auto;
color: $color-gray;
text-align: right;
@include bp (sm) {
border-radius: 16px;
margin-top: 24px;
}
&__illustration img {
opacity: 1;
a {
color: inherit;
text-decoration: none;
transition: color 0.3s;
&:hover {
color: $color-secondary;
span {
border-color: currentColor;
}
}
}
img {
display: inline-block;
width: 16px;
height: 16px;
margin: -2px 2px 0 0.25em;
border-radius: 100%;
}
span {
display: inline-block;
border-bottom: 1px solid rgba($color-gray, 0.25);
transition: border-color 0.3s;
}
}
}
@@ -262,88 +134,87 @@
margin: 128px 0 0;
}
.title {
grid-column: 1 / -1;
max-width: 400px;
margin: 0 auto 48px;
padding: 0 32px;
text-align: center;
& > .container {
align-items: center;
}
aside {
@include bp (sm) {
grid-column: 1 / -1;
margin-bottom: 80px;
padding: 0 16px;
grid-column: 3 / span 9;
}
h2 {
margin-bottom: 16px;
color: $color-secondary;
// Heading text
.heading {
max-width: 400px;
margin-bottom: 48px;
text-align: center;
@include bp (sm) {
margin-bottom: 24px;
margin-bottom: 80px;
text-align: left;
}
h2 {
margin-bottom: 16px;
color: $color-secondary;
@include bp (sm) {
margin-bottom: .5em;
}
}
p {
color: $color-tertiary;
font-weight: 300;
}
}
p {
color: $color-tertiary;
font-weight: 300;
// List of steps
ol {
li {
display: block;
margin: 6px 0;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
a {
display: block;
text-decoration: none;
color: $color-lilas-bright;
transition: color 0.3s;
&:hover {
color: $color-secondary-light;
}
}
.is-active {
a {
color: #fff;
}
}
}
}
// Steps grid
.steps {
--card-offset: 16px;
--card-margin: 40px;
grid-column: 1 / -1;
position: relative;
@include bp (sm) {
grid-column: 4 / -4;
padding-bottom: calc(var(--cards-amount) * var(--card-offset));
display: grid;
grid-template-rows: auto;
grid-column: 13 / span 11;
}
& > :global(*) {
grid-column: 1 / -1;
position: sticky;
top: var(--card-margin);
transform-origin: center top;
padding-top: calc(var(--index) * var(--card-offset));
padding-bottom: var(--card-margin);
margin-bottom: calc(-1 * var(--index) * var(--card-offset));
will-change: transform;
}
}
// Intention
.intention {
grid-column: 1 / -1;
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: min(45vw, 720px);
padding: 56px 32px;
border-radius: 12px;
background: $color-primary-darker;
color: $color-tertiary;
text-align: center;
@include bp (sm) {
--columns: 18;
grid-column: 4 / -4;
border-radius: 16px;
}
&__content {
width: clamp(250px, 75%, 562px);
margin: 0 auto;
}
:global(.globe) {
margin-bottom: 32px;
@include bp (sm) {
margin-bottom: 40px;
grid-row: 1;
grid-column: 1 / -1;
transform-origin: left center;
}
}
}