updates graphic block
|
|
@ -1,20 +0,0 @@
|
|||
<script lang="ts">
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* Whether to wrap the graphic with an aria hidden tag.
|
||||
*/
|
||||
hidden?: boolean;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { hidden = false, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#if hidden}
|
||||
<div aria-hidden="true">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{:else}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
215
src/components/GraphicBlock/GraphicBlock.mdx
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
import { Meta, Canvas } from '@storybook/blocks';
|
||||
|
||||
import * as GraphicBlockStories from './GraphicBlock.stories.svelte';
|
||||
|
||||
<Meta of={GraphicBlockStories} />
|
||||
|
||||
# GraphicBlock
|
||||
|
||||
The `GraphicBlock` component is a special derivative of the [Block](./?path=/docs/layout-block) component that wraps around your graphic. It also adds a title, description, notes and other text elements.
|
||||
|
||||
Many other Reuters Graphics components use `GraphicBlock` to wrap graphics with styled text.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { GraphicBlock } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<GraphicBlock
|
||||
title="Title for my chart"
|
||||
description="Some description for your chart."
|
||||
notes="Note: Data current as of Aug. 2, 2022.\n\nSource: [Google research](https://google.com)"
|
||||
>
|
||||
<!-- Your chart goes here -->
|
||||
<div id="my-chart" />
|
||||
</GraphicBlock>
|
||||
```
|
||||
|
||||
<Canvas of={GraphicBlockStories.Demo} />
|
||||
|
||||
## Using with ai2svelte and ArchieML docs
|
||||
|
||||
The `GraphicBlock` component is built to handle [ai2svelte](https://github.com/reuters-graphics/ai2svelte) graphics in Graphics Kit.
|
||||
|
||||
You'll likely get your text value from an ArchieML doc...
|
||||
|
||||
```yaml
|
||||
# ArchieML doc
|
||||
[blocks]
|
||||
type: ai-graphic
|
||||
width: normal
|
||||
chart: AiMap # IMPORTANT: This must match the name of the ai2svelte chart you import in App.svelte
|
||||
title: Earthquake in Haiti
|
||||
description: The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021.
|
||||
notes: \Note: A shakemap represents the ground shaking produced by an earthquake.
|
||||
|
||||
\Source: USGIS
|
||||
:end
|
||||
altText: A map that shows the shake intensity of the earthquake, which was worst in central Haiti.
|
||||
:end
|
||||
[]
|
||||
```
|
||||
|
||||
... which you'll parse out of a ArchieML block object before passing to the `GraphicBlock` component.
|
||||
|
||||
To pass your ai2svelte graphic into `GraphicBlock` component, import your ai2svelte graphic at the top of `App.svelte` and add it to the `aiCharts` object.
|
||||
|
||||
> **Important❗:** Make sure that the value for `chart` in the ArchieML doc matches the name of the ai2svelte file imported in `App.svelte`.
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
<script>
|
||||
// IMPORTANT: The name of your ai2svelte chart must match `chart` in your ArchieML doc
|
||||
import AiMap from './ai2svelte/my-map.svelte';
|
||||
// Error handler for missing ai2svelte charts
|
||||
import LogBlock from './components/dev/LogBlock.svelte';
|
||||
|
||||
// If using with the Graphics Kit
|
||||
import { assets } from '$app/paths';
|
||||
|
||||
// A built-in helper function in Graphis Kit for validating container width
|
||||
import { containerWidth } from '$utils/propValidators';
|
||||
|
||||
// Add your imported ai2svelte charts to this object
|
||||
const aiCharts = {
|
||||
AiMap,
|
||||
// Other ai2svelte graphics...
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Loop through ArchieML blocks -->
|
||||
{#each content.blocks as block}
|
||||
{#if block.type === 'ai-graphic'}
|
||||
{#if !aiCharts[block.chart]}
|
||||
<!-- Error message for when the ai2svelte chart is missing -->
|
||||
<LogBlock message={`Unable to find "${block.chart}" in aiCharts`} />
|
||||
{:else}
|
||||
<!-- Get the ai2svelte graphic specified by `chart` in ArchieML -->
|
||||
{@const AiChart = aiCharts[block.chart]}
|
||||
<GraphicBlock
|
||||
id={block.chart}
|
||||
width={containerWidth(block.width)}
|
||||
title={block.title}
|
||||
description={block.description}
|
||||
notes={block.notes}
|
||||
ariaDescription={block.altText}
|
||||
>
|
||||
<!-- In Graphics Kit, pass the `assetsPath` prop -->
|
||||
<AiChart assetsPath={assets || '/'} />
|
||||
</GraphicBlock>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
```
|
||||
|
||||
<Canvas of={GraphicBlockStories.Ai2SvelteAndArchieML} />
|
||||
|
||||
## Custom text
|
||||
|
||||
You can override the default styles for title and notes by making your own custom elements with the `customTitle` and `customNotes` [snippets](https://svelte.dev/docs/svelte/snippet):
|
||||
|
||||
```svelte
|
||||
<GraphicBlock>
|
||||
<!-- Custom title snippet -->
|
||||
{#snippet customTitle()}
|
||||
<h5>My smaller title</h5>
|
||||
{/snippet}
|
||||
|
||||
<!-- Your graphic -->
|
||||
<div id="my-chart"></div>
|
||||
|
||||
<!-- Custom notes snippet -->
|
||||
{#snippet customNotes()}
|
||||
<aside>
|
||||
<p><strong>Note:</strong> Data current as of Aug. 2, 2022.</p>
|
||||
</aside>
|
||||
{/snippet}
|
||||
</GraphicBlock>
|
||||
```
|
||||
|
||||
<Canvas of={GraphicBlockStories.CustomText} />
|
||||
|
||||
## ARIA descriptions
|
||||
|
||||
If the text in your chart isn't easily read by screen readers — for example, a map with annotations that wouldn't make sense without the visual — add an `ariaDescription` that describes the chart.
|
||||
|
||||
The `ariaDescription` string will be processed as markdown, so you can add multiple paragraphs, links, headers, etc. in markdown.
|
||||
|
||||
> **Note:** When you set an `ariaDescription`, your graphic will be automatically wrapped in a div with [aria-hidden="true"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-hidden), which tells screen readers to read the hidden ARIA description and skip the text in the graphic.
|
||||
|
||||
```svelte
|
||||
<GraphicBlock
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
ariaDescription="A map showing the shake intensity produced by the earthquake."
|
||||
>
|
||||
<!-- In Graphics Kit, pass the `assetsPath` prop -->
|
||||
<AiChart assetsPath={assets || '/'} />
|
||||
</GraphicBlock>
|
||||
```
|
||||
|
||||
<Canvas of={GraphicBlockStories.AriaDescription} />
|
||||
|
||||
## Custom ARIA descriptions
|
||||
|
||||
Sometimes, instead of a simple sentence, we want to provide a data table or something more complex as an ARIA description. To do this, use the `customAria` [snippet](https://svelte.dev/docs/svelte/snippet).
|
||||
|
||||
[Read this](https://accessibility.psu.edu/images/charts/) for more information on using screen reader data tables for charts.
|
||||
|
||||
> **Note:** The `customAria` snippet will override the `ariaDescription` and will also hide the text in your graphic from screen readers.
|
||||
|
||||
```svelte
|
||||
<GraphicBlock
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
>
|
||||
<!-- In Graphics Kit, pass the `assetsPath` prop -->
|
||||
<AiChart assetsPath={assets || '/'} />
|
||||
|
||||
<!-- Custom ARIA description snippet -->
|
||||
{#snippet customAria()}
|
||||
<p>
|
||||
A shakemap shows the intensity of the 7.2-magnitude earthquake that struck
|
||||
Haiti at 8:29 a.m. EST, Aug. 14, 2021.
|
||||
</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>City</th>
|
||||
<th>Felt shake strength</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Les Cayes</td>
|
||||
<td>Very strong</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jeremie</td>
|
||||
<td>Strong</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{/snippet}
|
||||
</GraphicBlock>
|
||||
|
||||
<!-- Optionally, style the visually hidden table nicely for sighted readers who use screen readers -->
|
||||
<style lang="scss">
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
<Canvas of={GraphicBlockStories.CustomAriaDescription} />
|
||||
|
|
@ -1,23 +1,10 @@
|
|||
<script module lang="ts">
|
||||
// @ts-ignore raw
|
||||
import componentDocs from './stories/docs/component.md?raw';
|
||||
// @ts-ignore raw
|
||||
import archieMLDocs from './stories/docs/archieML.md?raw';
|
||||
// @ts-ignore raw
|
||||
import customTextDocs from './stories/docs/customText.md?raw';
|
||||
// @ts-ignore raw
|
||||
import ai2svelteDocs from './stories/docs/ai2svelte.md?raw';
|
||||
// @ts-ignore raw
|
||||
import ariaDocs from './stories/docs/aria.md?raw';
|
||||
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import GraphicBlock from './GraphicBlock.svelte';
|
||||
|
||||
import { withComponentDocs, withStoryDocs } from '$docs/utils/withParams.js';
|
||||
|
||||
export const meta = {
|
||||
const { Story } = defineMeta({
|
||||
title: 'Components/Graphics/GraphicBlock',
|
||||
component: GraphicBlock,
|
||||
...withComponentDocs(componentDocs),
|
||||
argTypes: {
|
||||
width: {
|
||||
control: 'select',
|
||||
|
|
@ -28,92 +15,102 @@
|
|||
options: ['normal', 'wide', 'wider', 'widest', 'fluid'],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||
|
||||
import AiMap from './stories/ai2svelte/ai-chart.svelte';
|
||||
|
||||
// @ts-ignore img
|
||||
import PlaceholderImg from './stories/placeholder.png';
|
||||
import AiMap from './demo/ai2svelte/ai-chart.svelte';
|
||||
import PlaceholderImg from './demo/placeholder.png';
|
||||
</script>
|
||||
|
||||
<Template >
|
||||
{#snippet children({ args })}
|
||||
<GraphicBlock {...args}>
|
||||
<div class="demo-graphic">
|
||||
<img src="{PlaceholderImg}" alt="placeholder" />
|
||||
</div>
|
||||
</GraphicBlock>
|
||||
{/snippet}
|
||||
</Template>
|
||||
|
||||
<Story
|
||||
name="Default"
|
||||
args="{{
|
||||
width: 'normal',
|
||||
title: 'Bacon ipsum dolor amet t-bone',
|
||||
description:
|
||||
'Pork loin t-bone jowl prosciutto, short loin flank kevin tri-tip cupim pig pork. Meatloaf tri-tip frankfurter short ribs, cupim brisket bresaola chislic tail jerky burgdoggen pancetta.',
|
||||
notes:
|
||||
'Note: Data current as of Aug. 2, 2022.\n\nSource: [Google research](https://google.com)',
|
||||
}}"
|
||||
/>
|
||||
|
||||
<Story name="ArchieML" {...withStoryDocs(archieMLDocs)}>
|
||||
<Story name="Demo">
|
||||
<GraphicBlock
|
||||
title="Title for my chart"
|
||||
description="Some description for your chart."
|
||||
notes="Note: Data current as of Aug. 2, 2022.\n\nSource: [Google research](https://google.com)"
|
||||
>
|
||||
<!-- Graphic content -->
|
||||
<div id="my-chart">
|
||||
<img src={PlaceholderImg} alt="placeholder" />
|
||||
</div>
|
||||
</GraphicBlock>
|
||||
</Story>
|
||||
|
||||
<Story name="Ai2svelte and ArchieML" exportName="Ai2SvelteAndArchieML">
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
>
|
||||
<!-- Graphic content -->
|
||||
<AiMap />
|
||||
</GraphicBlock>
|
||||
</Story>
|
||||
|
||||
<Story name="Custom text" {...withStoryDocs(customTextDocs)}>
|
||||
<GraphicBlock width="normal">
|
||||
{#snippet title()}
|
||||
<div >
|
||||
<h5>My smaller title</h5>
|
||||
</div>
|
||||
{/snippet}
|
||||
<Story name="Custom text" exportName="CustomText">
|
||||
<GraphicBlock>
|
||||
<!-- Graphic content -->
|
||||
<div class="demo-graphic">
|
||||
<img src="{PlaceholderImg}" alt="placeholder" />
|
||||
<img src={PlaceholderImg} alt="placeholder" />
|
||||
</div>
|
||||
{#snippet notes()}
|
||||
<aside >
|
||||
|
||||
{#snippet customTitle()}
|
||||
<h5>My smaller title</h5>
|
||||
{/snippet}
|
||||
|
||||
{#snippet customNotes()}
|
||||
<aside>
|
||||
<p><strong>Note:</strong> Data current as of Aug. 2, 2022.</p>
|
||||
</aside>
|
||||
{/snippet}
|
||||
{/snippet}
|
||||
</GraphicBlock>
|
||||
</Story>
|
||||
|
||||
<Story name="Ai2svelte" {...withStoryDocs(ai2svelteDocs)}>
|
||||
<Story name="AREA description" exportName="AriaDescription">
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
>
|
||||
<AiMap />
|
||||
</GraphicBlock>
|
||||
</Story>
|
||||
|
||||
<Story name="ARIA" {...withStoryDocs(ariaDocs)}>
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
ariaDescription="A map showing the shake intensity produced by the earthquake."
|
||||
>
|
||||
<!-- Graphic content -->
|
||||
<AiMap />
|
||||
</GraphicBlock>
|
||||
</Story>
|
||||
|
||||
<Story name="Custom AREA description" exportName="CustomAriaDescription">
|
||||
<GraphicBlock
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
>
|
||||
<!-- Graphic content -->
|
||||
<AiMap />
|
||||
{#snippet customAria()}
|
||||
<p>
|
||||
A shakemap shows the intensity of the 7.2-magnitude earthquake that
|
||||
struck Haiti at 8:29 a.m. EST, Aug. 14, 2021.
|
||||
</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>City</th>
|
||||
<th>Felt shake strength</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Les Cayes</td>
|
||||
<td>Very strong</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jeremie</td>
|
||||
<td>Strong</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{/snippet}
|
||||
</GraphicBlock>
|
||||
</Story>
|
||||
|
||||
<style lang="scss">
|
||||
div.demo-graphic {
|
||||
height: 400px;
|
||||
|
|
@ -125,4 +122,18 @@
|
|||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
// Style the table nicely
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
th,
|
||||
td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,130 +1,138 @@
|
|||
<!-- @migration-task Error while migrating Svelte code: Cannot set properties of undefined (setting 'next') -->
|
||||
<!-- @component `GraphicBlock` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-graphics-graphicblock--docs) -->
|
||||
<script lang="ts">
|
||||
// Types
|
||||
import type { ContainerWidth } from '../@types/global';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
/**
|
||||
* Width of the component within the text well.
|
||||
* @type {string}
|
||||
*/
|
||||
export let width: ContainerWidth = 'normal';
|
||||
|
||||
/**
|
||||
* Add an id to the block tag to target it with custom CSS.
|
||||
* @type {string}
|
||||
*/
|
||||
export let id: string = '';
|
||||
/**
|
||||
* Add extra classes to the block tag to target it with custom CSS.
|
||||
* @type {string}
|
||||
*/
|
||||
let cls: string = '';
|
||||
export { cls as class };
|
||||
|
||||
/** Snap block to column widths, rather than fluidly resizing them. */
|
||||
export let snap: boolean = false;
|
||||
|
||||
/**
|
||||
* ARIA [role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles) for the block
|
||||
* @type {string}
|
||||
*/
|
||||
export let role: string | null = null;
|
||||
|
||||
/**
|
||||
* Notes to the graphic, passed in as a markdown string.
|
||||
* @type {string}
|
||||
*/
|
||||
export let notes: string | null = null;
|
||||
|
||||
/**
|
||||
* Set a different width for the text within the text well, for example,
|
||||
* "normal" to keep the title, description and notes inline with the rest
|
||||
* of the text well. Can't ever be wider than `width`.
|
||||
* @type {string}
|
||||
*/
|
||||
export let textWidth: ContainerWidth | null = 'normal';
|
||||
|
||||
/**
|
||||
* Title of the graphic
|
||||
* @type {string}
|
||||
*/
|
||||
export let title: string | null = null;
|
||||
|
||||
/**
|
||||
* Description of the graphic, passed in as a markdown string.
|
||||
* @type {string}
|
||||
*/
|
||||
export let description: string | null = null;
|
||||
|
||||
/**
|
||||
* ARIA [label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) for the block
|
||||
* @type {string}
|
||||
*/
|
||||
export let ariaLabel: string = 'chart';
|
||||
/**
|
||||
* ARIA description, passed in as a markdown string.
|
||||
* @type {string}
|
||||
*/
|
||||
export let ariaDescription: string | null = null;
|
||||
|
||||
import AriaHidden from './AriaHidden.svelte';
|
||||
import TextBlock from './TextBlock.svelte';
|
||||
// Components
|
||||
import AriaHidden from './components/AriaHidden.svelte';
|
||||
import TextBlock from './components/TextBlock.svelte';
|
||||
import Block from '../Block/Block.svelte';
|
||||
import PaddingReset from '../PaddingReset/PaddingReset.svelte';
|
||||
import Markdown from '../Markdown/Markdown.svelte';
|
||||
|
||||
interface Props {
|
||||
/** Content to place inside `GraphicBlock` */
|
||||
children: Snippet;
|
||||
/**
|
||||
* Add an id to the block tag to target it with custom CSS.
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
* Add classes to the block tag to target it with custom CSS.
|
||||
*/
|
||||
class?: string;
|
||||
/** Snap block to column widths, rather than fluidly resizing them. */
|
||||
snap?: boolean;
|
||||
/**
|
||||
* ARIA [role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles) for the block
|
||||
*/
|
||||
role?: string;
|
||||
/**
|
||||
* Notes to the graphic, passed in as a markdown string.
|
||||
*/
|
||||
notes?: string;
|
||||
/** Custom notes snippet */
|
||||
customNotes?: Snippet;
|
||||
/**
|
||||
* Width of the component within the text well.
|
||||
*/
|
||||
width?: ContainerWidth;
|
||||
/**
|
||||
* Set a different width for the text within the text well, for example, "normal" to keep the title, description and notes inline with the rest of the text well. Can't ever be wider than `width`.
|
||||
*/
|
||||
textWidth?: ContainerWidth;
|
||||
/**
|
||||
* Title of the graphic
|
||||
*/
|
||||
title?: string;
|
||||
/** Custom title snippet */
|
||||
customTitle?: Snippet;
|
||||
/**
|
||||
* Description of the graphic, passed in as a markdown string.
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* ARIA [label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) for the block
|
||||
*/
|
||||
ariaLabel?: string;
|
||||
/**
|
||||
* ARIA description, passed in as a markdown string.
|
||||
*/
|
||||
ariaDescription?: string;
|
||||
/** Custom ARIA snippet */
|
||||
customAria?: Snippet;
|
||||
}
|
||||
|
||||
let {
|
||||
children,
|
||||
id = '',
|
||||
class: cls = '',
|
||||
snap = false,
|
||||
role,
|
||||
notes,
|
||||
customNotes,
|
||||
width = 'normal',
|
||||
textWidth = 'normal',
|
||||
title,
|
||||
customTitle,
|
||||
description,
|
||||
ariaLabel = 'chart',
|
||||
ariaDescription,
|
||||
customAria,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<Block {id} {snap} {role} {width} {ariaLabel} class="graphic fmy-6 {cls}">
|
||||
{#if $$slots.title}
|
||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
||||
<TextBlock width="{textWidth}">
|
||||
<!-- Custom title content -->
|
||||
<slot name="title" />
|
||||
{#if customTitle}
|
||||
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||
<TextBlock width={textWidth}>
|
||||
<!-- Custom title snippet -->
|
||||
{@render customTitle()}
|
||||
</TextBlock>
|
||||
</PaddingReset>
|
||||
{:else if title}
|
||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
||||
<TextBlock width="{textWidth}">
|
||||
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||
<TextBlock width={textWidth}>
|
||||
<h3>{title}</h3>
|
||||
{#if description}
|
||||
<Markdown source="{description}" />
|
||||
<Markdown source={description} />
|
||||
{/if}
|
||||
</TextBlock>
|
||||
</PaddingReset>
|
||||
{/if}
|
||||
<AriaHidden hidden="{!!$$slots.aria || !!ariaDescription}">
|
||||
<AriaHidden hidden={!!customAria || !!ariaDescription}>
|
||||
<!-- Graphic content -->
|
||||
<slot />
|
||||
{@render children()}
|
||||
</AriaHidden>
|
||||
{#if $$slots.aria || ariaDescription}
|
||||
{#if customAria || ariaDescription}
|
||||
<div class="visually-hidden">
|
||||
{#if $$slots.aria}
|
||||
<!-- Custom ARIA markup -->
|
||||
<slot name="aria" />
|
||||
{:else}
|
||||
<Markdown source="{ariaDescription}" />
|
||||
{#if customAria}
|
||||
<!-- Custom ARIA snippet -->
|
||||
{@render customAria()}
|
||||
{:else if ariaDescription}
|
||||
<Markdown source={ariaDescription} />
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if $$slots.notes}
|
||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
||||
<TextBlock width="{textWidth}">
|
||||
{#if customNotes}
|
||||
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||
<TextBlock width={textWidth}>
|
||||
<!-- Custom notes content -->
|
||||
<slot name="notes" />
|
||||
{@render customNotes()}
|
||||
</TextBlock>
|
||||
</PaddingReset>
|
||||
{:else if notes}
|
||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
||||
<TextBlock width="{textWidth}">
|
||||
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||
<TextBlock width={textWidth}>
|
||||
<aside>
|
||||
<Markdown source="{notes}" />
|
||||
<Markdown source={notes} />
|
||||
</aside>
|
||||
</TextBlock>
|
||||
</PaddingReset>
|
||||
{/if}
|
||||
</Block>
|
||||
|
||||
<!-- svelte-ignore css-unused-selector -->
|
||||
<style lang="scss" global>
|
||||
@use '../../scss/mixins' as mixins;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
<script lang="ts">
|
||||
import type { ContainerWidth } from '../@types/global';
|
||||
|
||||
|
||||
import Block from '../Block/Block.svelte';
|
||||
interface Props {
|
||||
/** Width of the component within the text well. */
|
||||
width?: ContainerWidth | null;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { width = null, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#if width}
|
||||
<Block {width} class="notes fmy-0">
|
||||
{@render children?.()}
|
||||
</Block>
|
||||
{:else}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
21
src/components/GraphicBlock/components/AriaHidden.svelte
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* Whether to wrap the graphic with an aria hidden tag.
|
||||
*/
|
||||
hidden?: boolean;
|
||||
children: Snippet;
|
||||
}
|
||||
|
||||
let { hidden = false, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#if hidden && children}
|
||||
<div aria-hidden="true">
|
||||
{@render children()}
|
||||
</div>
|
||||
{:else if children}
|
||||
{@render children()}
|
||||
{/if}
|
||||
22
src/components/GraphicBlock/components/TextBlock.svelte
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { ContainerWidth } from '../../@types/global';
|
||||
|
||||
import Block from '../../Block/Block.svelte';
|
||||
interface Props {
|
||||
/** Width of the component within the text well. */
|
||||
width?: ContainerWidth;
|
||||
// children?: import('svelte').Snippet;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { width, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#if width && children}
|
||||
<Block {width} class="notes fmy-0">
|
||||
{@render children()}
|
||||
</Block>
|
||||
{:else if children}
|
||||
{@render children()}
|
||||
{/if}
|
||||
|
Before Width: | Height: | Size: 618 KiB After Width: | Height: | Size: 618 KiB |
|
Before Width: | Height: | Size: 388 KiB After Width: | Height: | Size: 388 KiB |
|
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
|
@ -1,19 +0,0 @@
|
|||
A more detailed example of using `GraphicBlock` with components created by [ai2svelte](https://github.com/reuters-graphics/ai2svelte).
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { GraphicBlock } from '@reuters-graphics/graphics-components';
|
||||
import MyAiMap from './ai2svelte/my-map.svelte';
|
||||
import { assets } from '$app/paths'; // If using with the Graphics Kit
|
||||
</script>
|
||||
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
ariaDescription="A map showing shake intensity of the quake."
|
||||
>
|
||||
<MyAiMap assetsPath="{assets}" />
|
||||
</GraphicBlock>
|
||||
```
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
For Graphics Kit users, the `GraphicBlock` component is built-in to handle [ai2svelte](https://github.com/reuters-graphics/ai2svelte) graphics.
|
||||
|
||||
First, import your ai2svelte graphic in `App.svelte` and add it to the `aiCharts` object;
|
||||
|
||||
```svelte
|
||||
<!-- App.svelte -->
|
||||
<script>
|
||||
// Other stuff...
|
||||
|
||||
import AiMap from './ai2svelte/my-map.svelte';
|
||||
|
||||
const aiCharts = {
|
||||
// Other charts...
|
||||
AiMap,
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
Then add the following structure to your ArchieML doc, taking care that the name of your chart in the `aiCharts` object matches the name of your `chart`:
|
||||
|
||||
```yaml
|
||||
[blocks]
|
||||
# ...
|
||||
|
||||
type: ai-graphic
|
||||
chart: AiMap
|
||||
width: normal
|
||||
textWidth: normal
|
||||
title: Earthquake in Haiti
|
||||
description: The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021.
|
||||
notes: \Note: A shakemap represents the ground shaking produced by an earthquake.
|
||||
|
||||
\Source: USGIS
|
||||
:end
|
||||
altText: A map that shows the shake intensity of the earthquake, which was worst in central Haiti.
|
||||
:end
|
||||
|
||||
# ...
|
||||
[]
|
||||
```
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
If your chart isn't easily read by screen readers — for example, it has annotations that when read without the visual won't make sense — you should add an `ariaDescription` that better describes the chart.
|
||||
|
||||
The `ariaDescription` string will be processed as markdown, so you can add multiple paragraphs, links, headers or whatever else you need in markdown.
|
||||
|
||||
> **Note:** When you set an `ariaDescription`, your graphic will be automatically wrapped in a div that tells screen readers not to read the text in the graphic, but instead read the hidden ARIA description.
|
||||
|
||||
```svelte
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
ariaDescription="A map showing the shake intensity produced by the earthquake."
|
||||
>
|
||||
<MyAiMap assetsPath="{assets}" />
|
||||
</GraphicBlock>
|
||||
```
|
||||
|
||||
Sometimes, instead of a simple ARIA description for graphics, we want to also provide a data table or something else that requires more complex markup.
|
||||
|
||||
You can add custom markup for screen readers only by using the `aria` named slot.
|
||||
|
||||
> **Note:** The `aria` slot will override the `ariaDescription` and will also hide the text in your graphic from screen readers.
|
||||
|
||||
```svelte
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
title="Earthquake in Haiti"
|
||||
description="The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021."
|
||||
notes="Note: A shakemap represents the ground shaking produced by an earthquake."
|
||||
>
|
||||
<MyAiMap basePath="{assets}" />
|
||||
<div slot="aria">
|
||||
<p>
|
||||
A shakemap shows the intensity of the 7.2-magnitude earthquake that struck
|
||||
Haiti at 8:29 a.m. EST, Aug. 14, 2021.
|
||||
</p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>City</th>
|
||||
<th>Felt shake strength</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Les Cayes</td>
|
||||
<td>Very strong</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jeremie</td>
|
||||
<td>Strong</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</GraphicBlock>
|
||||
```
|
||||
|
||||
[Read this](https://accessibility.psu.edu/images/charts/) for more information on using screen reader data tables for charts.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
The `GraphicBlock` component is a special derivative of the [`Block`](./?path=/docs/layout-block) component that also handles text elements around a graphic.
|
||||
|
||||
Many other components use this one to wrap graphics with styled text. When you use it, you'll also wrap your chart elements or component with it like this:
|
||||
|
||||
---
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { GraphicBlock } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
title="Title for my chart"
|
||||
description="Pork loin t-bone jowl prosciutto, short loin flank kevin tri-tip cupim pig pork. Meatloaf tri-tip frankfurter short ribs, cupim brisket bresaola chislic tail jerky burgdoggen pancetta."
|
||||
notes="Note: Data current as of Aug. 2, 2022.\n\nSource: [Google research](https://google.com)"
|
||||
>
|
||||
<div id="my-chart"></div>
|
||||
</GraphicBlock>
|
||||
```
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
You can override the markup used to generate the chart text elements by using the `title` and/or `notes` named slots like this:
|
||||
|
||||
```svelte
|
||||
<GraphicBlock
|
||||
width="normal"
|
||||
notes="{'Note: Data current as of Aug. 2, 2022.\n\nSource: [Google research](https://google.com)'}"
|
||||
>
|
||||
<h5 slot="title">My smaller title</h5>
|
||||
<div id="my-chart"></div>
|
||||
<aside slot="notes">
|
||||
<p><strong>Note:</strong> Data current as of Aug. 2, 2022.</p>
|
||||
</aside>
|
||||
</GraphicBlock>
|
||||
```
|
||||