done!
This commit is contained in:
parent
9839e34f49
commit
c7c38fd1cc
20 changed files with 481 additions and 295 deletions
|
|
@ -45,7 +45,7 @@ export interface ScrollerStep {
|
|||
*/
|
||||
foregroundProps?: object;
|
||||
/**
|
||||
* Optional alt text for the background, read aloud after the foregroud text. You can add it to each step or just to the first step to describe the entire scroller graphic.
|
||||
* Optional alt text for the background, read aloud after the foreground text. You can add it to each step or just to the first step to describe the entire scroller graphic.
|
||||
*/
|
||||
altText?: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,12 @@
|
|||
|
||||
interface Props {
|
||||
index: number;
|
||||
steps?: ScrollerStep[];
|
||||
steps: ScrollerStep[];
|
||||
preload?: number;
|
||||
stackBackground?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
index,
|
||||
steps = [],
|
||||
preload = 1,
|
||||
stackBackground = true,
|
||||
}: Props = $props();
|
||||
let { index, steps, preload = 1, stackBackground = true }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#each steps as step, i}
|
||||
|
|
@ -22,8 +17,8 @@
|
|||
{#if preload === 0 || (i >= (stackBackground ? 0 : index - preload) && i <= index + preload)}
|
||||
<div
|
||||
class="step-background step-{i + 1} w-full absolute"
|
||||
class:visible="{stackBackground ? i <= index : i === index}"
|
||||
class:invisible="{stackBackground ? i > index : i !== index}"
|
||||
class:visible={stackBackground ? i <= index : i === index}
|
||||
class:invisible={stackBackground ? i > index : i !== index}
|
||||
>
|
||||
<step.background {...step.backgroundProps || {}}></step.background>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -17,18 +17,18 @@
|
|||
|
||||
{#if typeof step.altText === 'string'}
|
||||
<div class="background-alt-text visually-hidden">
|
||||
<Markdown source="{step.altText}" />
|
||||
<Markdown source={step.altText} />
|
||||
</div>
|
||||
{/if}
|
||||
{:else if typeof step.foreground === 'string'}
|
||||
<Block class="body-text step-{index + 1}">
|
||||
<div class="embedded-foreground step-{index + 1}">
|
||||
<Markdown source="{step.foreground}" />
|
||||
<Markdown source={step.foreground} />
|
||||
</div>
|
||||
|
||||
{#if typeof step.altText === 'string'}
|
||||
<div class="background-alt-text visually-hidden">
|
||||
<Markdown source="{step.altText}" />
|
||||
<Markdown source={step.altText} />
|
||||
</div>
|
||||
{/if}
|
||||
</Block>
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
import Background from './Background.svelte';
|
||||
import Foreground from './Foreground.svelte';
|
||||
interface Props {
|
||||
steps?: ScrollerStep[];
|
||||
steps: ScrollerStep[];
|
||||
embeddedLayout?: EmbeddedLayout;
|
||||
backgroundWidth?: ContainerWidth;
|
||||
}
|
||||
|
||||
let {
|
||||
steps = [],
|
||||
steps,
|
||||
embeddedLayout = 'fb',
|
||||
backgroundWidth = 'fluid',
|
||||
}: Props = $props();
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
import Markdown from '../Markdown/Markdown.svelte';
|
||||
interface Props {
|
||||
steps?: ScrollerStep[];
|
||||
steps: ScrollerStep[];
|
||||
}
|
||||
|
||||
let { steps = [] }: Props = $props();
|
||||
let { steps }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#each steps as step, i}
|
||||
|
|
@ -19,20 +19,20 @@
|
|||
<div class="empty-step-foreground"></div>
|
||||
{#if typeof step.altText === 'string'}
|
||||
<div class="background-alt-text visually-hidden">
|
||||
<Markdown source="{step.altText}" />
|
||||
<Markdown source={step.altText} />
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="step-foreground w-full">
|
||||
{#if typeof step.foreground === 'string'}
|
||||
<Markdown source="{step.foreground}" />
|
||||
<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}" />
|
||||
<Markdown source={step.altText} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,274 @@ import * as ScrollerStories from './Scroller.stories.svelte';
|
|||
|
||||
# Scroller
|
||||
|
||||
The `Scroller` component TK.
|
||||
The `Scroller` component creates a basic scrollytelling graphic with layout options.
|
||||
|
||||
> This component is designed to handle most common layouts for scrollytelling. To make something more complex, customise [ScrollerBase](https://github.com/reuters-graphics/graphics-components/blob/main/src/components/Scroller/ScrollerBase/index.svelte), which is a Svelte 5 version of the [svelte-scroller](https://github.com/sveltejs/svelte-scroller).
|
||||
|
||||
[Demo](?path=/story/components-graphics-scroller--demo)
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Scroller } from '@reuters-graphics/graphics-components';
|
||||
|
||||
import MyBackground from './MyBackground.svelte'; // Your own background component
|
||||
|
||||
// Array of step objects that define the steps in your scroller.
|
||||
const steps = [
|
||||
{
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'red' }, // Optional props for your background component
|
||||
foreground: '#### Step 1\n\nLorem ipsum red',
|
||||
altText: 'Red background',
|
||||
},
|
||||
{
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'blue' },
|
||||
foreground: '#### Step 2\n\nLorem ipsum blue',
|
||||
altText: 'Blue background',
|
||||
},
|
||||
{
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'green' },
|
||||
foreground: '#### Step 3\n\nLorem ipsum green',
|
||||
altText: 'Green background',
|
||||
},
|
||||
],
|
||||
</script>
|
||||
|
||||
<Scroller />
|
||||
<Scroller {steps} foregroundPosition="middle" backgroundWidth="fluid" />
|
||||
```
|
||||
|
||||
## Using with ArchieML and ai2svelte
|
||||
|
||||
[Demo](?path=/story/components-graphics-scroller--archie-ml)
|
||||
|
||||
In your Graphics Kit project, import your ai2svelte graphics in `App.svelte` and add them to the `aiCharts` object:
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
<script>
|
||||
import AiMap1 from './ai2svelte/my-map-1.svelte';
|
||||
import AiMap2 from './ai2svelte/my-map-2.svelte';
|
||||
import AiMap3 from './ai2svelte/my-map-3.svelte';
|
||||
|
||||
import content from '$locales/en/content.json';
|
||||
|
||||
// Graphics Kit only
|
||||
import { assets } from '$app/paths'; // 👈 If using in the Graphics Kit...
|
||||
import { truthy } from '$utils/propValidators'; // 👈 If using in the Graphics Kit...
|
||||
|
||||
const aiCharts = {
|
||||
AiMap1,
|
||||
AiMap2,
|
||||
AiMap3,
|
||||
// Other charts...
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
Then add the following structure to your ArchieML Doc, making sure that the names of your charts in the `aiCharts` object match the names of each step's `background` in the ArchieML doc:
|
||||
|
||||
```yaml
|
||||
# ArchieML doc
|
||||
[blocks]
|
||||
type: ai-scroller
|
||||
id: my-map-scroller
|
||||
width: fluid
|
||||
foregroundPosition: right
|
||||
stackBackground: true
|
||||
|
||||
# Array of step objects
|
||||
[.steps]
|
||||
background: AiMap1
|
||||
foreground: #### Step 1
|
||||
|
||||
Here's where something happend.
|
||||
:end
|
||||
altText: A map showing the Upper West side in New York City.
|
||||
|
||||
Can add paragraphs of alt text if you want to break up sentences.
|
||||
:end
|
||||
|
||||
background: AiMap2
|
||||
foreground: #### Step 2
|
||||
|
||||
Something happened on some street...
|
||||
:end
|
||||
altText: The same map now highlights 98th Street.
|
||||
:end
|
||||
|
||||
background: AiMap3
|
||||
foreground: #### Step 3
|
||||
|
||||
... and now there are multiple protests.
|
||||
:end
|
||||
altText: The same map now highlights three locations near 98th Street where something particulary important happened.
|
||||
:end
|
||||
[]
|
||||
[]
|
||||
```
|
||||
|
||||
Then parse the relevant ArchieML block object before passing to the `Scroller` component.
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
{#each content.blocks as block}
|
||||
{#if block.type === 'ai-scroller'}
|
||||
<Scroller
|
||||
id={block.id}
|
||||
backgroundWidth={block.width}
|
||||
foregroundPosition={block.foregroundPosition}
|
||||
stackBackground={truthy(block.stackBackground)}
|
||||
steps={block.steps.map((step) => ({
|
||||
background: aiCharts[step.background],
|
||||
backgroundProps: { assetsPath: assets || '/' },
|
||||
foreground: step.foreground,
|
||||
altText: step.altText,
|
||||
}))}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
```
|
||||
|
||||
> **Note:** Some props, like `stackBackground`, expect boolean values. If you're using the Graphics Kit, use the `truthy()` util function to convert a string value to a boolean.
|
||||
|
||||
> **Note:** In Graphics Kit, the image source paths in ai2svelte components have to be fixed by passing `assets` to each step object, like in the example above.
|
||||
|
||||
## Custom foreground
|
||||
|
||||
[Demo](?path=/story/components-graphics-scroller--custom-foreground)
|
||||
|
||||
Instead of just text, you can use components as foregrounds, and optionally pass props to it.
|
||||
|
||||
If you're customising your own foreground component, remember to add alt text that describes the background graphic.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import MyBackground from './MyBackground.svelte'; // Your own background component
|
||||
import MyInteractiveForeground from './MyInteractiveForeground.svelte'; // Your custom foreground component
|
||||
|
||||
const steps = [
|
||||
{
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'red' }, // Props for your background component, if needed
|
||||
foreground: MyInteractiveForeground, // Custom foreground component
|
||||
},
|
||||
{
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'blue' },
|
||||
foreground: '#### Step 2\n\nLorem ipsum blue', // You can still add a markdown string as foreground; you can mix and match
|
||||
},
|
||||
{
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'green' },
|
||||
foreground: MyInteractiveForeground,
|
||||
foregroundProps: { count: 100 }, // Props for your custom foreground component, if needed
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<Scroller {steps} />
|
||||
```
|
||||
|
||||
## Custom foreground with ArchieML
|
||||
|
||||
[Demo](?path=/story/components-graphics-scroller--customforeground-archie-ml)
|
||||
|
||||
You can use custom foreground components with ArchieML with a few additional steps.
|
||||
|
||||
In your Graphics Kit project's `App.svelte`, import your custom foregroud components and add them to a `foregroundComponents` object, just as you import ai2svelte background graphics and add them to the `aiCharts` object:
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
<script>
|
||||
import content from '$locales/en/content.json';
|
||||
|
||||
// Background ai2svelte graphics
|
||||
import AiMap1 from './ai2svelte/my-map-1.svelte';
|
||||
import AiMap2 from './ai2svelte/my-map-2.svelte';
|
||||
import AiMap3 from './ai2svelte/my-map-3.svelte';
|
||||
|
||||
// Foreground components, which can be ai2svelte or not.
|
||||
import Foreground1 from './ai2svelte/my-foreground-1.svelte';
|
||||
|
||||
// Graphics Kit only
|
||||
import { assets } from '$app/paths'; // 👈 If using in the Graphics Kit...
|
||||
import { truthy } from '$utils/propValidators'; // 👈 If using in the Graphics Kit...
|
||||
|
||||
// Background ai2svelte graphics components
|
||||
const aiCharts = {
|
||||
AiMap1,
|
||||
AiMap2,
|
||||
AiMap3,
|
||||
// Other charts...
|
||||
};
|
||||
|
||||
// Foreground components
|
||||
const foregroundComponents = {
|
||||
Foreground1,
|
||||
// Other components...
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
Then add the following structure to your ArchieML Doc, making sure that the names of your charts in the `aiCharts` and `foregroundComponents` objects match the names of each step's `background` and `foreground` in the ArchieML doc:
|
||||
|
||||
```yaml
|
||||
# ArchieML doc
|
||||
[blocks]
|
||||
type: ai-scroller
|
||||
id: my-map-scroller
|
||||
foregroundPosition: left
|
||||
stackBackground: true
|
||||
|
||||
# Array of step objects
|
||||
[.steps]
|
||||
background: AiMap1
|
||||
# You can still use a markdown string even if other step/s use a custom foreground component
|
||||
foreground: #### Step 1
|
||||
|
||||
Here's where something happend.
|
||||
:end
|
||||
altText: A map showing the Upper West side in New York City.
|
||||
:end
|
||||
|
||||
background: AiMap2
|
||||
foreground: Foreground1 # The name of your custom foreground component
|
||||
altText: The same map now highlights 98th Street.
|
||||
:end
|
||||
background: AiMap3
|
||||
foreground: #### Step 3
|
||||
|
||||
... and now there are multiple protests.
|
||||
:end
|
||||
altText: The same map now highlights three locations near 98th Street where something particulary important happened.
|
||||
:end
|
||||
[]
|
||||
[]
|
||||
```
|
||||
|
||||
Then parse the relevant ArchieML block object before passing to the `Scroller` component.
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
{#each content.blocks as block}
|
||||
{#if block.type === 'ai-scroller'}
|
||||
<Scroller
|
||||
id={block.id}
|
||||
backgroundWidth={block.width}
|
||||
foregroundPosition={block.foregroundPosition}
|
||||
stackBackground={truthy(block.stackBackground)}
|
||||
steps={block.steps.map((step) => ({
|
||||
background: aiCharts[step.background],
|
||||
backgroundProps: { assetsPath: assets || '/' },
|
||||
foreground: foregroundComponents[step.foreground] || step.foreground,
|
||||
foregroundProps: { assetsPath: assets || '/' },
|
||||
altText: step.altText,
|
||||
}))}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
```
|
||||
|
||||
> **Note:** You only need to pass `foregroundProps: { assetsPath: assets || '/' }` in Graphics Kit if your foreground components are ai2svelte graphicss.
|
||||
|
|
|
|||
|
|
@ -24,38 +24,69 @@
|
|||
</script>
|
||||
|
||||
<script>
|
||||
import BasicStep from './demo/components/basic/Step.svelte';
|
||||
import InteractiveForeground from './demo/components/basic/InteractiveForeground.svelte';
|
||||
import MyBackground from './demo/components/basic/Step.svelte';
|
||||
import MyInteractiveForeground from './demo/components/basic/InteractiveForeground.svelte';
|
||||
|
||||
// ai2svelte backgrounds
|
||||
import AiMap1 from './demo/components/ai2svelte/ai-scroller-1.svelte';
|
||||
import AiMap2 from './demo/components/ai2svelte/ai-scroller-2.svelte';
|
||||
import AiMap3 from './demo/components/ai2svelte/ai-scroller-3.svelte';
|
||||
|
||||
// ai2svelte foreground
|
||||
import AiForeground from './demo/components/ai2svelte/ai-foreground.svelte';
|
||||
|
||||
const aiCharts = {
|
||||
AiMap1,
|
||||
AiMap2,
|
||||
AiMap3,
|
||||
};
|
||||
|
||||
const foregroundComponents = {
|
||||
AiForeground,
|
||||
};
|
||||
|
||||
const docBlock = {
|
||||
type: 'scroller',
|
||||
width: 'fluid',
|
||||
foregroundPosition: 'middle',
|
||||
foregroundPosition: 'right',
|
||||
id: 'my-scroller',
|
||||
stackBackground: true,
|
||||
stackBackground: 'true',
|
||||
steps: [
|
||||
{
|
||||
background: aiCharts.AiMap1,
|
||||
text: '#### Step 1\n\nLorem ipsum',
|
||||
foreground: "#### Step 1\n\nHere's where something happend.",
|
||||
altText: 'A map showing the Upper West side in New York City.',
|
||||
},
|
||||
{
|
||||
background: aiCharts.AiMap2,
|
||||
text: '#### Step 2\n\nLorem ipsum',
|
||||
foreground: '#### Step 2\n\nSomething happened on some street...',
|
||||
altText: 'The same map now highlights 98th Street.',
|
||||
},
|
||||
{
|
||||
background: aiCharts.AiMap3,
|
||||
text: '#### Step 3\n\nLorem ipsum',
|
||||
foreground: '#### Step 3\n\n... and now there are multiple protests.',
|
||||
altText:
|
||||
'The same map now highlights three locations near 98th Street where something particulary important happened.',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const docBlockCustomForeground = {
|
||||
foregroundPosition: 'left',
|
||||
id: 'my-scroller',
|
||||
stackBackground: 'true',
|
||||
steps: [
|
||||
{
|
||||
background: aiCharts.AiMap1,
|
||||
foreground: "#### Step 1\n\nHere's where something happend.",
|
||||
altText: 'A map showing the Upper West side in New York City.',
|
||||
},
|
||||
{
|
||||
background: aiCharts.AiMap2,
|
||||
foreground: foregroundComponents.AiForeground,
|
||||
altText: 'The same map now highlights 98th Street.',
|
||||
},
|
||||
{
|
||||
background: aiCharts.AiMap3,
|
||||
foreground: '#### Step 3\n\n... and now there are multiple protests.',
|
||||
altText:
|
||||
'The same map now highlights three locations near 98th Street where something particulary important happened.',
|
||||
},
|
||||
|
|
@ -68,19 +99,19 @@
|
|||
args={{
|
||||
steps: [
|
||||
{
|
||||
background: BasicStep,
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'red' },
|
||||
foreground: '#### Step 1\n\nLorem ipsum red',
|
||||
altText: 'Red background',
|
||||
},
|
||||
{
|
||||
background: BasicStep,
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'blue' },
|
||||
foreground: '#### Step 2\n\nLorem ipsum blue',
|
||||
altText: 'Blue background',
|
||||
},
|
||||
{
|
||||
background: BasicStep,
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'green' },
|
||||
foreground: '#### Step 3\n\nLorem ipsum green',
|
||||
altText: 'Green background',
|
||||
|
|
@ -88,68 +119,61 @@
|
|||
],
|
||||
foregroundPosition: 'middle',
|
||||
backgroundWidth: 'fluid',
|
||||
embeddedLayout: 'fb',
|
||||
embedded: false,
|
||||
}}
|
||||
/>
|
||||
<Story name="ArchieML" args={docBlock} />
|
||||
|
||||
<Story name="ArchieML and ai2svelte" exportName="ArchieML">
|
||||
<Scroller
|
||||
id={docBlock.id}
|
||||
backgroundWidth={docBlock.width}
|
||||
foregroundPosition={docBlock.foregroundPosition}
|
||||
stackBackground={docBlock.stackBackground === 'true'}
|
||||
steps={docBlock.steps.map((step) => ({
|
||||
background: step.background,
|
||||
foreground: step.foreground,
|
||||
altText: step.altText,
|
||||
}))}
|
||||
/>
|
||||
</Story>
|
||||
|
||||
<Story
|
||||
name="Foreground components"
|
||||
name="Custom foreground"
|
||||
exportName="CustomForeground"
|
||||
args={{
|
||||
steps: [
|
||||
{
|
||||
background: BasicStep,
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'red' },
|
||||
foreground: InteractiveForeground,
|
||||
foreground: MyInteractiveForeground,
|
||||
},
|
||||
{
|
||||
background: BasicStep,
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'blue' },
|
||||
foreground: '#### Step 2\n\nLorem ipsum blue',
|
||||
},
|
||||
{
|
||||
background: BasicStep,
|
||||
background: MyBackground,
|
||||
backgroundProps: { colour: 'green' },
|
||||
foreground: InteractiveForeground,
|
||||
foreground: MyInteractiveForeground,
|
||||
foregroundProps: { count: 100 },
|
||||
},
|
||||
],
|
||||
foregroundPosition: 'middle',
|
||||
backgroundWidth: 'fluid',
|
||||
embeddedLayout: 'fb',
|
||||
embedded: false,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Ai2svelte"
|
||||
args={{
|
||||
steps: [
|
||||
{
|
||||
background: AiMap1,
|
||||
backgroundProps: { colour: 'red' },
|
||||
foreground: '#### Step 1\n\nLorem ipsum',
|
||||
altText: 'A map showing the Upper West side in New York City.',
|
||||
},
|
||||
{
|
||||
background: AiMap2,
|
||||
backgroundProps: { colour: 'blue' },
|
||||
foreground: '#### Step 2\n\nLorem ipsum',
|
||||
altText:
|
||||
'The same map now highlights 98th Street where something interesting happened.',
|
||||
},
|
||||
{
|
||||
background: AiMap3,
|
||||
backgroundProps: { colour: 'green' },
|
||||
foreground: '#### Step 3\n\nLorem ipsum',
|
||||
altText:
|
||||
'The same map now highlights three locations near 98th Street where something particulary important happened.',
|
||||
},
|
||||
],
|
||||
foregroundPosition: 'middle',
|
||||
backgroundWidth: 'fluid',
|
||||
embeddedLayout: 'fb',
|
||||
embedded: false,
|
||||
}}
|
||||
/>
|
||||
name="Custom foreground with ArchiemL"
|
||||
exportName="CustomforegroundArchieML"
|
||||
>
|
||||
<Scroller
|
||||
id={docBlockCustomForeground.id}
|
||||
backgroundWidth={docBlockCustomForeground.width}
|
||||
foregroundPosition={docBlockCustomForeground.foregroundPosition}
|
||||
stackBackground={docBlockCustomForeground.stackBackground === 'true'}
|
||||
steps={docBlockCustomForeground.steps.map((step) => ({
|
||||
background: step.background,
|
||||
foreground: step.foreground,
|
||||
altText: step.altText,
|
||||
}))}
|
||||
/>
|
||||
</Story>
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@
|
|||
} from '../@types/global';
|
||||
|
||||
interface Props {
|
||||
/** ID of the scroller container */
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* An array of step objects that define the steps in your scroller.
|
||||
*
|
||||
|
|
@ -26,7 +23,7 @@
|
|||
* - `backgroundProps` Optional props for background component.
|
||||
* - `foreground` A component or markdown-formatted string. **REQUIRED**
|
||||
* - `foregroundProps` Optional props for foreground component.
|
||||
* - `altText` Optional alt text for the background, read aloud after the foregroud text. You can add it to each step or just to the first step to describe the entire scroller graphic. **RECOMMENDED**
|
||||
* - `altText` Optional alt text for the background, read aloud after the foreground text. You can add it to each step or just to the first step to describe the entire scroller graphic. **RECOMMENDED**
|
||||
*
|
||||
*/
|
||||
steps: ScrollerStep[];
|
||||
|
|
@ -73,6 +70,8 @@
|
|||
* Parallax prop passed to [svelte-scroller](https://github.com/sveltejs/svelte-scroller#parameters)
|
||||
*/
|
||||
parallax?: boolean;
|
||||
/** ID of the scroller container */
|
||||
id?: string;
|
||||
/** Set a class to target with SCSS */
|
||||
class?: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
<script>
|
||||
// Hard-coding for demo purposes only...
|
||||
import stepXs from './images/Body-issues-key-xs.png';
|
||||
let width = $state();
|
||||
</script>
|
||||
|
||||
<div id="g-Body-issues-key-box" bind:clientWidth={width}>
|
||||
<!-- Artboard: xs -->
|
||||
{#if width && width >= 0}
|
||||
<div id="g-Body-issues-key-xs" class="g-artboard" style="">
|
||||
<div style="padding: 0 0 48.4848% 0;"></div>
|
||||
<div
|
||||
id="g-Body-issues-key-xs-img"
|
||||
class="g-aiImg"
|
||||
alt=""
|
||||
style="background-image: url({stepXs});"
|
||||
></div>
|
||||
<div
|
||||
id="g-ai0-1"
|
||||
class="g-Layer_1 g-aiAbs g-aiPointText"
|
||||
style="top:19.4775%;margin-top:-10.2px;left:8.1818%;width:276px;"
|
||||
>
|
||||
<p class="g-pstyle0">Likelihood of something happening</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="g-ai0-3"
|
||||
class="g-Layer_1 g-aiAbs g-aiPointText"
|
||||
style="top:55.1025%;margin-top:-10.2px;left:27.2727%;width:68px;"
|
||||
>
|
||||
<p class="g-pstyle1">0-25%</p>
|
||||
</div>
|
||||
<div
|
||||
id="g-ai0-4"
|
||||
class="g-Layer_1 g-aiAbs g-aiPointText"
|
||||
style="top:55.1025%;margin-top:-10.2px;left:74.2424%;width:75px;"
|
||||
>
|
||||
<p class="g-pstyle1">50-75%</p>
|
||||
</div>
|
||||
<div
|
||||
id="g-ai0-5"
|
||||
class="g-Layer_1 g-aiAbs g-aiPointText"
|
||||
style="top:79.4775%;margin-top:-10.2px;left:74.2424%;width:82px;"
|
||||
>
|
||||
<p class="g-pstyle1">75-100%</p>
|
||||
</div>
|
||||
<div
|
||||
id="g-ai0-6"
|
||||
class="g-Layer_1 g-aiAbs g-aiPointText"
|
||||
style="top:83.2275%;margin-top:-10.2px;left:27.2727%;width:77px;"
|
||||
>
|
||||
<p class="g-pstyle1">25-50%</p>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- End ai2html - 2025-03-17 09:52 -->
|
||||
|
||||
<!-- Generated by ai2html v0.100.0 - 2025-03-17 09:52 -->
|
||||
<!-- ai file: Body-issues-key.ai -->
|
||||
<style lang="scss">
|
||||
#g-Body-issues-key-box,
|
||||
#g-Body-issues-key-box .g-artboard {
|
||||
margin: 0 auto;
|
||||
}
|
||||
#g-Body-issues-key-box p {
|
||||
margin: 0;
|
||||
}
|
||||
#g-Body-issues-key-box .g-aiAbs {
|
||||
position: absolute;
|
||||
}
|
||||
#g-Body-issues-key-box .g-aiImg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
display: block;
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
#g-Body-issues-key-box .g-aiPointText p {
|
||||
white-space: nowrap;
|
||||
}
|
||||
#g-Body-issues-key-xs {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
#g-Body-issues-key-xs p {
|
||||
font-family: 'Knowledge', 'Source Sans Pro', Arial, sans-serif;
|
||||
font-weight: 500;
|
||||
line-height: 19px;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
letter-spacing: 0em;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
color: rgb(64, 64, 64);
|
||||
text-transform: none;
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
mix-blend-mode: normal;
|
||||
font-style: normal;
|
||||
position: static;
|
||||
}
|
||||
#g-Body-issues-key-xs .g-pstyle0 {
|
||||
height: 19px;
|
||||
}
|
||||
#g-Body-issues-key-xs .g-pstyle1 {
|
||||
font-weight: 400;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
/* Custom CSS */
|
||||
.text {
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,21 +1,16 @@
|
|||
<script>
|
||||
// Hard-coding for demo purposes only...
|
||||
// @ts-ignore img
|
||||
import stepXl from './images/step-1-xl.png';
|
||||
// @ts-ignore img
|
||||
import stepLg from './images/step-1-lg.png';
|
||||
// @ts-ignore img
|
||||
import stepMd from './images/step-1-md.png';
|
||||
// @ts-ignore img
|
||||
import stepSm from './images/step-1-sm.png';
|
||||
// @ts-ignore img
|
||||
import stepXs from './images/step-1-xs.png';
|
||||
let width = $state();
|
||||
</script>
|
||||
|
||||
<!-- Generated by ai2html v0.100.0 - 2021-09-30 14:21 -->
|
||||
|
||||
<div id="g-step-1-box" bind:clientWidth="{width}">
|
||||
<div id="g-step-1-box" bind:clientWidth={width}>
|
||||
<!-- Artboard: XL -->
|
||||
{#if width && width >= 1200}
|
||||
<div id="g-step-1-xl" class="g-artboard" style="">
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 606 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 376 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 219 KiB |
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
<h4>Interactive step</h4>
|
||||
|
||||
<p>The count is {count}</p>
|
||||
<p class="font-sans">The count is <strong>{count}</strong></p>
|
||||
|
||||
<button
|
||||
onclick="{() => {
|
||||
onclick={() => {
|
||||
count += 1;
|
||||
}}">Click Me</button
|
||||
}}>Click Me</button
|
||||
>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
let { colour = 'lightblue' }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="step" style="{`background: ${colour};`}"></div>
|
||||
<div class="step" style={`background: ${colour};`}></div>
|
||||
|
||||
<style lang="scss">
|
||||
.step {
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
A more detailed example of using `Scroller` with graphics created by [ai2svelte](https://github.com/reuters-graphics/ai2svelte).
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Scroller } from '@reuters-graphics/graphics-components';
|
||||
|
||||
import MyAiMap1 from './ai2svelte/my-map-step-1.svelte';
|
||||
import MyAiMap2 from './ai2svelte/my-map-step-2.svelte';
|
||||
import MyAiMap3 from './ai2svelte/my-map-step-3.svelte';
|
||||
|
||||
import { assets } from '$app/paths'; // If using with the Graphics Kit
|
||||
|
||||
const steps = [
|
||||
{
|
||||
background: MyAiMap1,
|
||||
backgroundProps: { assetsPath: assets },
|
||||
foreground: '#### Step 1\n\nLorem ipsum',
|
||||
altText: 'A map showing TKTK',
|
||||
},
|
||||
{
|
||||
background: MyAiMap2,
|
||||
backgroundProps: { assetsPath: assets },
|
||||
foreground: '#### Step 2\n\nLorem ipsum',
|
||||
altText: 'The same map now highlights something interesting.',
|
||||
},
|
||||
{
|
||||
background: MyAiMap3,
|
||||
backgroundProps: { assetsPath: assets },
|
||||
foreground: '#### Step 3\n\nLorem ipsum',
|
||||
altText: 'The same map now shows something else that is interesting.',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<Scroller
|
||||
steps="{steps}"
|
||||
backgroundWidth="fluid"
|
||||
foregroundPosition="middle"
|
||||
stackBackground="{true}"
|
||||
embedded="{false}"
|
||||
/>
|
||||
```
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
First, import your ai2svelte graphics in `App.svelte` and add them to the `aiCharts` object;
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
<script>
|
||||
// Other stuff...
|
||||
|
||||
import AiMap1 from './ai2svelte/my-map-1.svelte';
|
||||
import AiMap2 from './ai2svelte/my-map-2.svelte';
|
||||
import AiMap3 from './ai2svelte/my-map-3.svelte';
|
||||
|
||||
const aiCharts = {
|
||||
// Other charts...
|
||||
AiMap1,
|
||||
AiMap2,
|
||||
AiMap3,
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
Then add the following structure to your ArchieML Doc, taking care that the names of your charts in the `aiCharts` object match the names of your step backgrounds:
|
||||
|
||||
```yaml
|
||||
[blocks]
|
||||
# ...
|
||||
|
||||
type: ai-scroller
|
||||
id: my-map-scroller
|
||||
width: normal
|
||||
foregroundPosition: middle
|
||||
stackBackground: true
|
||||
[.steps]
|
||||
background: AiMap1
|
||||
text: #### Step 1
|
||||
|
||||
Lorem ipsum
|
||||
:end
|
||||
altText: A map showing the Upper West side in New York City.
|
||||
|
||||
Can add paragraphs of alt text if you want to break up sentences.
|
||||
:end
|
||||
|
||||
background: AiMap2
|
||||
text: #### Step 2
|
||||
|
||||
Lorem ipsum
|
||||
:end
|
||||
altText: The same map now highlights 98th Street.
|
||||
:end
|
||||
|
||||
background: AiMap3
|
||||
text: #### Step 3
|
||||
|
||||
Lorem ipsum
|
||||
:end
|
||||
altText: The same map now highlights three locations near 98th Street where something particulary important happened.
|
||||
:end
|
||||
[]
|
||||
|
||||
# ...
|
||||
[]
|
||||
```
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
{#each content.blocks as block}
|
||||
{#if block.type === 'text'}
|
||||
<!-- ... -->
|
||||
|
||||
{:else if block.type === 'ai-scroller'}
|
||||
<Scroller
|
||||
id="{block.id}"
|
||||
backgroundWidth="{block.width}"
|
||||
foregroundPosition="{block.foregroundPosition}"
|
||||
stackBackground="{block.stackBackground === 'true'}"
|
||||
steps="{block.steps.map((step) => ({
|
||||
background: aiCharts[step.background],
|
||||
backgroundProps: { assetsPath: assets || '/' },
|
||||
foreground: step.text,
|
||||
altText: step.altText,
|
||||
}))}"
|
||||
/>
|
||||
|
||||
<!-- ... -->
|
||||
{/if}
|
||||
{/each}
|
||||
```
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
The `Scroller` component helps you quickly create basic scrollytelling graphics with several layout options.
|
||||
|
||||
> This component is designed to handle most common layouts for scrollytelling. If you need something more complex, though, you should probably use [svelte-scroller](https://github.com/sveltejs/svelte-scroller), which is a lower level component you can more easily customize.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Scroller } from '@reuters-graphics/graphics-components';
|
||||
|
||||
import MyColourBackground from './MyColourBackground.svelte';
|
||||
|
||||
const steps = [
|
||||
{
|
||||
background: MyColourBackground,
|
||||
backgroundProps: { colour: 'red' },
|
||||
foreground: '#### Step 1\n\nLorem ipsum red',
|
||||
altText: 'Red background',
|
||||
},
|
||||
{
|
||||
background: MyColourBackground,
|
||||
backgroundProps: { colour: 'blue' },
|
||||
foreground: '#### Step 2\n\nLorem ipsum blue',
|
||||
altText: 'Blue background',
|
||||
},
|
||||
{
|
||||
background: MyColourBackground,
|
||||
backgroundProps: { colour: 'green' },
|
||||
foreground: '#### Step 3\n\nLorem ipsum green',
|
||||
altText: 'Green background',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<Scroller
|
||||
steps="{steps}"
|
||||
backgroundWidth="fluid"
|
||||
foregroundPosition="middle"
|
||||
embedded="{false}"
|
||||
/>
|
||||
```
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
Instead of just text, you can use any component in the foreground, too, and pass whatever props you need to it.
|
||||
|
||||
If you're making your own custom foreground component, remember to add alt text describing the background graphic.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
// ...
|
||||
import MyCounter from './MyCounter.svelte';
|
||||
|
||||
const steps = [
|
||||
{
|
||||
background: MyColourBackground,
|
||||
backgroundProps: { colour: 'red' },
|
||||
foreground: MyCounter,
|
||||
},
|
||||
{
|
||||
background: MyColourBackground,
|
||||
backgroundProps: { colour: 'blue' },
|
||||
foreground: '#### Step 2\n\nLorem ipsum blue',
|
||||
},
|
||||
{
|
||||
background: MyColourBackground,
|
||||
backgroundProps: { colour: 'green' },
|
||||
foreground: MyCounter,
|
||||
foregroundProps: { count: 100 },
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<Scroller
|
||||
steps="{steps}"
|
||||
backgroundWidth="fluid"
|
||||
foregroundPosition="middle"
|
||||
embedded="{false}"
|
||||
/>
|
||||
```
|
||||
Loading…
Reference in a new issue