Refactor
This commit is contained in:
parent
4712d80d4d
commit
a95cc32580
8 changed files with 294 additions and 418 deletions
|
|
@ -1,51 +0,0 @@
|
|||
<script lang="ts">
|
||||
import type { ScrollerStep } from '../@types/global';
|
||||
|
||||
interface Props {
|
||||
index: number;
|
||||
steps: ScrollerStep[];
|
||||
preload?: number;
|
||||
stackBackground?: boolean;
|
||||
}
|
||||
|
||||
let { index, steps, preload = 1, stackBackground = true }: Props = $props();
|
||||
|
||||
function showStep(i: number) {
|
||||
if (preload === 0) return true;
|
||||
if (stackBackground) return i >= 0;
|
||||
return i >= index - preload && i <= index + preload;
|
||||
}
|
||||
|
||||
function isVisible(i: number) {
|
||||
if (stackBackground) return i <= index;
|
||||
return i === index;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#each steps as step, i}
|
||||
{#if showStep(i)}
|
||||
<div
|
||||
class={`step-background step-${i + 1} w-full absolute`}
|
||||
class:visible={isVisible(i)}
|
||||
class:invisible={!isVisible(i)}
|
||||
>
|
||||
<step.background {...step.backgroundProps || {}}></step.background>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
<style lang="scss">
|
||||
.step-background {
|
||||
opacity: 0;
|
||||
will-change: opacity;
|
||||
transition: 0.35s opacity ease;
|
||||
|
||||
&.visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.invisible {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
<script lang="ts">
|
||||
import type { ScrollerStep } from '../@types/global';
|
||||
|
||||
import { Markdown } from '@reuters-graphics/svelte-markdown';
|
||||
|
||||
interface Props {
|
||||
steps: ScrollerStep[];
|
||||
}
|
||||
|
||||
let { steps }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#each steps as step, i}
|
||||
<div
|
||||
class="step-foreground-container step-{i +
|
||||
1} mb-20 h-screen flex items-center justify-center"
|
||||
>
|
||||
{#if step.foreground === '' || !step.foreground}
|
||||
<!-- Empty foreground -->
|
||||
<div class="empty-step-foreground"></div>
|
||||
{#if typeof step.altText === 'string'}
|
||||
<div class="background-alt-text visually-hidden">
|
||||
<Markdown source={step.altText} />
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="step-foreground w-full">
|
||||
{#if typeof step.foreground === 'string'}
|
||||
<Markdown source={step.foreground} />
|
||||
{:else}
|
||||
<step.foreground {...step.foregroundProps || {}}></step.foreground>
|
||||
{/if}
|
||||
</div>
|
||||
{#if typeof step.altText === 'string'}
|
||||
<div class="background-alt-text visually-hidden">
|
||||
<Markdown source={step.altText} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
<style lang="scss">
|
||||
@use './mixins' as mixins;
|
||||
|
||||
div.step-foreground-container {
|
||||
width: initial;
|
||||
max-width: initial;
|
||||
.step-foreground {
|
||||
max-width: calc(mixins.$column-width-normal * 0.9);
|
||||
border-radius: 0.25rem;
|
||||
@include mixins.fpy-5;
|
||||
@include mixins.fpx-4;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
|
||||
:global(p:last-child) {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
:global(*:first-child) {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
186
src/components/ScrollerAnimate/ScrollerAnimate.svelte
Normal file
186
src/components/ScrollerAnimate/ScrollerAnimate.svelte
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
<script lang="ts">
|
||||
import ScrollerBase from '../ScrollerBase/ScrollerBase.svelte';
|
||||
import Squash from './Squash.svelte';
|
||||
import GraphicBlock from '../GraphicBlock/GraphicBlock.svelte';
|
||||
import Block from '../Block/Block.svelte';
|
||||
|
||||
import type {
|
||||
ContainerWidth,
|
||||
ForegroundPosition,
|
||||
} from '../@types/global';
|
||||
|
||||
type Graphic = {
|
||||
src: string;
|
||||
srcset: string;
|
||||
alt: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
notes?: string;
|
||||
width?: ContainerWidth;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
graphics: Graphic[];
|
||||
/** Duration of the squash animation in milliseconds. */
|
||||
animationDuration?: number;
|
||||
/** When to swap the image during the animation (0–1). E.g. 0.8 = swap at 80% through. */
|
||||
animationPeak?: number;
|
||||
/** Width of the background */
|
||||
backgroundWidth?: ContainerWidth;
|
||||
/** Position of the foreground */
|
||||
foregroundPosition?: ForegroundPosition;
|
||||
/** Threshold prop passed to svelte-scroller */
|
||||
threshold?: number;
|
||||
/** Top prop passed to svelte-scroller */
|
||||
top?: number;
|
||||
/** Bottom prop passed to svelte-scroller */
|
||||
bottom?: number;
|
||||
/** Parallax prop passed to svelte-scroller */
|
||||
parallax?: boolean;
|
||||
/** ID of the scroller container */
|
||||
id?: string;
|
||||
/** Set a class to target with SCSS */
|
||||
class?: string;
|
||||
/** The currently active section */
|
||||
index?: number;
|
||||
/** How far the section has scrolled past the threshold */
|
||||
offset?: number;
|
||||
/** How far the foreground has travelled */
|
||||
progress?: number;
|
||||
}
|
||||
|
||||
let {
|
||||
graphics,
|
||||
animationDuration = 350,
|
||||
animationPeak = 0.8,
|
||||
backgroundWidth = 'fluid',
|
||||
foregroundPosition = 'middle',
|
||||
threshold = 0.5,
|
||||
top = 0,
|
||||
bottom = 1,
|
||||
parallax = false,
|
||||
id = '',
|
||||
class: cls = '',
|
||||
index = $bindable(0),
|
||||
offset = $bindable(0),
|
||||
progress = $bindable(0),
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<Block width="fluid" class="scroller-container {cls}" {id}>
|
||||
<ScrollerBase
|
||||
bind:index
|
||||
bind:offset
|
||||
bind:progress
|
||||
{threshold}
|
||||
{top}
|
||||
{bottom}
|
||||
{parallax}
|
||||
query="div.step-foreground-container"
|
||||
>
|
||||
{#snippet backgroundSnippet()}
|
||||
<div
|
||||
class="background min-h-screen relative p-0 flex justify-center"
|
||||
class:right={foregroundPosition === 'left opposite'}
|
||||
class:left={foregroundPosition === 'right opposite'}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="scroller-graphic-well w-full">
|
||||
<Block
|
||||
width={backgroundWidth}
|
||||
class="background-container my-0 min-h-screen flex justify-center items-center relative"
|
||||
>
|
||||
<Squash
|
||||
{graphics}
|
||||
{index}
|
||||
{offset}
|
||||
{animationDuration}
|
||||
{animationPeak}
|
||||
{backgroundWidth}
|
||||
/>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
{#snippet foregroundSnippet()}
|
||||
<div class="foreground {foregroundPosition} w-full">
|
||||
{#each graphics as graphic}
|
||||
<div class="step-foreground-container">
|
||||
<GraphicBlock
|
||||
title={graphic.title}
|
||||
description={graphic.description}
|
||||
notes={graphic.notes}
|
||||
>
|
||||
<!-- GraphicBlock requires the children snippet to be defined, but currently, our image is in the background snippet. -->
|
||||
{''}
|
||||
</GraphicBlock>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/snippet}
|
||||
</ScrollerBase>
|
||||
</Block>
|
||||
|
||||
<style lang="scss">
|
||||
div.background {
|
||||
&.left {
|
||||
width: 50%;
|
||||
float: left;
|
||||
@media (max-width: 1200px) {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
float: initial;
|
||||
}
|
||||
}
|
||||
&.right {
|
||||
width: 50%;
|
||||
float: right;
|
||||
@media (max-width: 1200px) {
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
float: initial;
|
||||
}
|
||||
}
|
||||
|
||||
div.scroller-graphic-well {
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
div.foreground {
|
||||
&.right {
|
||||
width: 50%;
|
||||
float: right;
|
||||
@media (max-width: 1200px) {
|
||||
width: 100%;
|
||||
float: initial;
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
width: 50%;
|
||||
float: left;
|
||||
@media (max-width: 1200px) {
|
||||
width: 100%;
|
||||
float: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-foreground-container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 1em;
|
||||
margin: 0 auto;
|
||||
max-width: var(--normal-column-width, 660px);
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
|
||||
> :global(*) {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
95
src/components/ScrollerAnimate/Squash.svelte
Normal file
95
src/components/ScrollerAnimate/Squash.svelte
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
<script lang="ts">
|
||||
import { getResponsiveSizes } from '@utils/propValidators';
|
||||
import type { ContainerWidth } from '@components/@types/global';
|
||||
|
||||
type Graphic = {
|
||||
src: string;
|
||||
srcset: string;
|
||||
alt: string;
|
||||
width?: ContainerWidth;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
graphics: Graphic[];
|
||||
index: number;
|
||||
offset: number;
|
||||
animationDuration?: number;
|
||||
animationPeak?: number;
|
||||
backgroundWidth?: ContainerWidth;
|
||||
}
|
||||
|
||||
let {
|
||||
graphics,
|
||||
index,
|
||||
offset,
|
||||
animationDuration = 350,
|
||||
animationPeak = 0.8,
|
||||
backgroundWidth = 'fluid',
|
||||
}: Props = $props();
|
||||
|
||||
let imgEl = $state<HTMLImageElement | null>(null);
|
||||
|
||||
// The target step graphic we want to transition to based on scroll position
|
||||
let targetIndex = $derived(
|
||||
offset >= animationPeak && index < graphics.length - 1 ? index + 1 : index
|
||||
);
|
||||
|
||||
// The actual graphic currently visible on screen
|
||||
let displayedIndex = $state(0);
|
||||
|
||||
$effect(() => {
|
||||
// When the target index changes, fire the animation but delay the graphic swap!
|
||||
if (targetIndex !== displayedIndex) {
|
||||
if (imgEl) {
|
||||
// Force a browser reflow to instantly restart the time-based animation
|
||||
imgEl.style.animation = 'none';
|
||||
imgEl.offsetHeight;
|
||||
imgEl.style.animation = '';
|
||||
}
|
||||
|
||||
const swapTimeout = setTimeout(() => {
|
||||
displayedIndex = targetIndex;
|
||||
}, animationDuration * 0.8);
|
||||
|
||||
return () => clearTimeout(swapTimeout);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<img
|
||||
bind:this={imgEl}
|
||||
class="graphic"
|
||||
style="--animation-time: {animationDuration}ms;"
|
||||
src={graphics[displayedIndex].src}
|
||||
srcset={graphics[displayedIndex].srcset}
|
||||
sizes={getResponsiveSizes(backgroundWidth)}
|
||||
alt={graphics[displayedIndex].alt}
|
||||
/>
|
||||
|
||||
<style lang="scss">
|
||||
.graphic {
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
transform-origin: bottom center;
|
||||
animation: squash var(--animation-time) linear(0, 0.417 25.5%, 0.867 49.4%, 1 57.7%, 0.925 65.1%, 0.908 68.6%, 0.902 72.2%, 0.916 78.2%, 0.988 92.1%, 1) forwards;
|
||||
}
|
||||
|
||||
@keyframes squash {
|
||||
0% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
50% {
|
||||
scale: 0.8 1.2;
|
||||
translate: 0 -8px;
|
||||
}
|
||||
80% {
|
||||
scale: 1.4 0.6;
|
||||
translate: 0 -16px;
|
||||
}
|
||||
100% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
<script lang="ts">
|
||||
import ScrollerBase from '../ScrollerBase/ScrollerBase.svelte';
|
||||
import type { ContainerWidth } from '../@types/global';
|
||||
|
||||
type Graphic = {
|
||||
src: string;
|
||||
srcset: string;
|
||||
alt: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
notes?: string;
|
||||
width?: ContainerWidth;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
graphics: Graphic[];
|
||||
/** Duration of the squash animation in milliseconds. */
|
||||
animationDuration?: number;
|
||||
/** When to swap the image during the animation (0–1). E.g. 0.8 = swap at 80% through. */
|
||||
animationSwap?: number;
|
||||
/**
|
||||
* Raw CSS string injected into the document head for this component instance.
|
||||
* Use the `.graphic` selector to target the image element.
|
||||
* Define any required @keyframes here too.
|
||||
*
|
||||
* @example
|
||||
* graphicCss="@keyframes bounce { to { translate: 0 -20px; } } .graphic { animation: bounce 0.5s ease alternate infinite; }"
|
||||
*/
|
||||
graphicCss?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
graphics,
|
||||
animationDuration = 350,
|
||||
animationSwap = 0.8,
|
||||
graphicCss,
|
||||
}: Props = $props();
|
||||
|
||||
let count = $state(1);
|
||||
let index = $state(0);
|
||||
let offset = $state(0);
|
||||
let progress = $state(0);
|
||||
|
||||
let displayedIndex = $state(0);
|
||||
let imgEl = $state<HTMLImageElement | null>(null);
|
||||
|
||||
// Inject graphicCss into the document head as a real style element.
|
||||
$effect(() => {
|
||||
if (!graphicCss) return;
|
||||
const style = document.createElement('style');
|
||||
style.textContent = graphicCss;
|
||||
document.head.appendChild(style);
|
||||
return () => style.remove();
|
||||
});
|
||||
|
||||
// On index change: reset the CSS animation, then swap the graphic at the
|
||||
// configured point through the animation (animationSwap).
|
||||
$effect(() => {
|
||||
const newIndex = index; // track reactive dependency
|
||||
if (!imgEl) return;
|
||||
|
||||
imgEl.style.animation = 'none';
|
||||
imgEl.offsetHeight; // force reflow to restart the animation
|
||||
imgEl.style.animation = '';
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
displayedIndex = newIndex;
|
||||
}, animationDuration * animationSwap);
|
||||
|
||||
return () => clearTimeout(timeout);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="photo-scroller">
|
||||
<ScrollerBase
|
||||
bind:count
|
||||
bind:index
|
||||
bind:offset
|
||||
bind:progress
|
||||
query="div.step-foreground-container"
|
||||
>
|
||||
{#snippet backgroundSnippet()}
|
||||
<img
|
||||
bind:this={imgEl}
|
||||
class="graphic"
|
||||
style="--animation-time: {animationDuration}ms"
|
||||
src={graphics[displayedIndex].src}
|
||||
srcset={graphics[displayedIndex].srcset}
|
||||
sizes="(min-width: 690px) 660px, calc(100vw - 30px)"
|
||||
alt={graphics[displayedIndex].alt}
|
||||
/>
|
||||
{/snippet}
|
||||
|
||||
{#snippet foregroundSnippet()}
|
||||
{#each graphics as graphic}
|
||||
<div class="step-foreground-container">
|
||||
{#if graphic.title}<h2>{graphic.title}</h2>{/if}
|
||||
{#if graphic.description}<p>{graphic.description}</p>{/if}
|
||||
{#if graphic.notes}<aside>{graphic.notes}</aside>{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/snippet}
|
||||
</ScrollerBase>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.graphic {
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
transform-origin: bottom center;
|
||||
animation: squash var(--animation-time) linear(0, 0.417 25.5%, 0.867 49.4%, 1 57.7%, 0.925 65.1%, 0.908 68.6%, 0.902 72.2%, 0.916 78.2%, 0.988 92.1%, 1) forwards;
|
||||
}
|
||||
|
||||
@keyframes squash {
|
||||
0% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
scale: 0.8 1.2;
|
||||
translate: 0 -8px;
|
||||
}
|
||||
|
||||
80% {
|
||||
scale: 1.4 0.6;
|
||||
translate: 0 -16px;
|
||||
}
|
||||
|
||||
100% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.step-foreground-container {
|
||||
height: 50vh;
|
||||
padding: 1em;
|
||||
margin: 0 0 2em 0;
|
||||
max-width: var(--normal-column-width, 660px);
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,15 +1,11 @@
|
|||
<script lang="ts">
|
||||
import ScrollerBase from '../components/ScrollerBase/ScrollerBase.svelte';
|
||||
import { getResponsiveSizes } from '../utils/propValidators';
|
||||
|
||||
import ScrollerSquash from '@components/ScrollerAnimate/ScrollerAnimate.svelte';
|
||||
|
||||
// Types
|
||||
import type {
|
||||
ContainerWidth,
|
||||
ForegroundPosition,
|
||||
ScrollerStep,
|
||||
} from '../components/@types/global';
|
||||
import Article from '@components/Article/Article.svelte';
|
||||
} from '@components/@types/global';
|
||||
|
||||
type Graphic = {
|
||||
src: string;
|
||||
|
|
@ -19,10 +15,8 @@
|
|||
description?: string;
|
||||
notes?: string;
|
||||
width?: ContainerWidth;
|
||||
|
||||
};
|
||||
|
||||
|
||||
interface Props {
|
||||
graphics: Graphic[];
|
||||
/** Duration of the animation, milliseconds **/
|
||||
|
|
@ -42,132 +36,13 @@
|
|||
foregroundPosition = 'middle',
|
||||
animationDuration = 350,
|
||||
animationPeak = 0.8,
|
||||
}: Props = $props();
|
||||
|
||||
let count = $state(1);
|
||||
let index = $state(0);
|
||||
let offset = $state(0);
|
||||
let progress = $state(0);
|
||||
|
||||
// reset animation on index change, swap graphic at peak distortion (80%)
|
||||
let displayedIndex = $state(0);
|
||||
let imgEl = $state<HTMLImageElement | null>(null);
|
||||
$effect(() => {
|
||||
const newIndex = index; // track changes
|
||||
if (!imgEl) return;
|
||||
imgEl.style.animation = 'none';
|
||||
imgEl.offsetHeight; // force reflow
|
||||
imgEl.style.animation = '';
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
displayedIndex = newIndex;
|
||||
}, animationDuration * animationPeak);
|
||||
|
||||
return () => clearTimeout(timeout);
|
||||
});
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<Article>
|
||||
|
||||
<ScrollerBase
|
||||
bind:count
|
||||
bind:index
|
||||
bind:offset
|
||||
bind:progress
|
||||
query="div.step-foreground-container"
|
||||
>
|
||||
{#snippet backgroundSnippet()}
|
||||
<div
|
||||
class="background min-h-screen relative p-0 flex justify-center"
|
||||
class:right={foregroundPosition === 'left opposite'}
|
||||
class:left={foregroundPosition === 'right opposite'}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<img
|
||||
bind:this={imgEl}
|
||||
class="graphic"
|
||||
style="--animation-time: {animationDuration}ms"
|
||||
src={graphics[displayedIndex].src}
|
||||
srcset={graphics[displayedIndex].srcset}
|
||||
sizes={getResponsiveSizes(backgroundWidth)}
|
||||
alt={graphics[displayedIndex].alt}
|
||||
/>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
{#snippet foregroundSnippet()}
|
||||
{#each graphics as graphic, i}
|
||||
<div class="step-foreground-container">
|
||||
{#if graphic.title}<h2>{graphic.title}</h2>{/if}
|
||||
{#if graphic.description}<p>{graphic.description}</p>{/if}
|
||||
{#if graphic.notes}<aside>{graphic.notes}</aside>{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/snippet}
|
||||
</ScrollerBase>
|
||||
</Article>
|
||||
|
||||
<style lang="scss">
|
||||
@use 'mixins' as mixins;
|
||||
|
||||
.graphic {
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
transform-origin: bottom center;
|
||||
animation: squash var(--animation-time) linear(0, 0.417 25.5%, 0.867 49.4%, 1 57.7%, 0.925 65.1%, 0.908 68.6%, 0.902 72.2%, 0.916 78.2%, 0.988 92.1%, 1) forwards;
|
||||
}
|
||||
|
||||
@keyframes squash {
|
||||
0% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
scale: 0.8 1.2;
|
||||
translate: 0 -8px;
|
||||
}
|
||||
|
||||
80% {
|
||||
scale: 1.4 0.6;
|
||||
translate: 0 -16px;
|
||||
}
|
||||
|
||||
100% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
}
|
||||
// we play this
|
||||
@keyframes stretch {
|
||||
0% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
scale: 0.8 1.2;
|
||||
translate: 0 -8px;
|
||||
}
|
||||
|
||||
80% {
|
||||
scale: 1.4 0.6;
|
||||
translate: 0 -16px;
|
||||
}
|
||||
|
||||
100% {
|
||||
scale: 1;
|
||||
translate: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.step-foreground-container {
|
||||
height: 50vh;
|
||||
/* background-color: rgba(0, 0, 0, 0.2); */
|
||||
padding: 1em;
|
||||
margin: 0 0 2em 0;
|
||||
max-width: var(--normal-column-width, 660px);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
</style>
|
||||
<ScrollerSquash
|
||||
{graphics}
|
||||
{animationDuration}
|
||||
{animationPeak}
|
||||
{backgroundWidth}
|
||||
{foregroundPosition}
|
||||
/>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import Squash from './Squash.svelte';
|
||||
import ScrollerAnimate from '@components/ScrollerAnimate/ScrollerAnimate.svelte';
|
||||
|
||||
import Article from '@components/Article/Article.svelte';
|
||||
import BodyText from '@components/BodyText/BodyText.svelte';
|
||||
|
|
@ -35,7 +35,7 @@ const graphics = await Promise.all([
|
|||
/>
|
||||
<Article>
|
||||
<BodyText text="Cras eu consectetur justo, eu luctus felis. Suspendisse lectus enim, bibendum vitae euismod et, condimentum quis tortor. Donec sit amet orci nibh. Vivamus facilisis nunc quis nunc feugiat placerat. Nunc ut augue vitae metus fermentum venenatis vel at dui. Nulla aliquet nibh porttitor odio imperdiet, in ullamcorper augue bibendum. Cras ornare nunc ut sollicitudin egestas. Suspendisse neque ipsum, faucibus eu hendrerit porttitor, tincidunt a tortor. Aliquam at facilisis diam, a ullamcorper lacus. Suspendisse pharetra faucibus venenatis. Donec efficitur condimentum neque ut vehicula." />
|
||||
<Squash client:only="svelte" {graphics} backgroundWidth="normal" />
|
||||
<ScrollerAnimate client:only="svelte" {graphics} backgroundWidth="normal" />
|
||||
<BodyText text="Sed feugiat, lacus id elementum tristique, urna elit consectetur mauris, in commodo ipsum neque sed turpis. Ut elit ex, pharetra laoreet leo vitae, rhoncus condimentum ligula. Morbi et sagittis tellus. Proin sed felis euismod ipsum lacinia feugiat. Donec finibus pretium dignissim. Integer ornare egestas scelerisque. Donec purus elit, viverra vitae felis at, volutpat sollicitudin tellus. Vivamus fermentum dictum dapibus. Phasellus non ligula ac augue efficitur ultrices sit amet at quam. Fusce dapibus luctus ex, non semper massa commodo eget." />
|
||||
</Article>
|
||||
</Layout>
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
|
||||
import Article from '@components/Article/Article.svelte';
|
||||
import BodyText from '@components/BodyText/BodyText.svelte';
|
||||
import Headline from '@components/Headline/Headline.svelte';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Headline
|
||||
hed={'Unfriendly skies'}
|
||||
/>
|
||||
<Article>
|
||||
<BodyText text="Cras eu consectetur justo, eu luctus felis. Suspendisse lectus enim, bibendum vitae euismod et, condimentum quis tortor. Donec sit amet orci nibh. Vivamus facilisis nunc quis nunc feugiat placerat. Nunc ut augue vitae metus fermentum venenatis vel at dui. Nulla aliquet nibh porttitor odio imperdiet, in ullamcorper augue bibendum. Cras ornare nunc ut sollicitudin egestas. Suspendisse neque ipsum, faucibus eu hendrerit porttitor, tincidunt a tortor. Aliquam at facilisis diam, a ullamcorper lacus. Suspendisse pharetra faucibus venenatis. Donec efficitur condimentum neque ut vehicula." />
|
||||
<BodyText text="Sed feugiat, lacus id elementum tristique, urna elit consectetur mauris, in commodo ipsum neque sed turpis. Ut elit ex, pharetra laoreet leo vitae, rhoncus condimentum ligula. Morbi et sagittis tellus. Proin sed felis euismod ipsum lacinia feugiat. Donec finibus pretium dignissim. Integer ornare egestas scelerisque. Donec purus elit, viverra vitae felis at, volutpat sollicitudin tellus. Vivamus fermentum dictum dapibus. Phasellus non ligula ac augue efficitur ultrices sit amet at quam. Fusce dapibus luctus ex, non semper massa commodo eget." />
|
||||
</Article>
|
||||
</Layout>
|
||||
Loading…
Reference in a new issue