Merge pull request #243 from reuters-graphics/mf-photo

Updates FeaturePhoto
This commit is contained in:
MinamiFunakoshiTR 2025-04-07 10:17:14 -05:00 committed by GitHub
commit 6c854957e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 159 additions and 158 deletions

View file

@ -0,0 +1,72 @@
import { Meta, Canvas } from '@storybook/blocks';
import * as FeaturePhotoStories from './FeaturePhoto.stories.svelte';
<Meta of={FeaturePhotoStories} />
# FeaturePhoto
The `FeaturePhoto` component adds a full-width photo.
```svelte
<script>
import { FeaturePhoto } from '@reuters-graphics/graphics-components';
import { assets } from '$app/paths'; // 👈 If using in the Graphics Kit...
</script>
<FeaturePhoto
src={`${assets}/images/myImage.jpg`}
altText="Some alt text"
caption="A caption"
/>
```
<Canvas of={FeaturePhotoStories.Demo} />
## Using with ArchieML docs
With the Graphics Kit, you'll likely get your text value from an ArchieML doc...
```yaml
# ArchieML doc
[blocks]
type: photo
width: normal
src: images/shark.jpg
altText: The king of the sea
caption: Carcharodon carcharias - REUTERS
[]
```
... which you'll parse out of a ArchieML block object before passing to the `FeaturePhoto` component.
```svelte
<!-- App.svelte -->
<script>
import { FeaturePhoto } from '@reuters-graphics/graphics-components';
import content from '$locales/en/content.json';
import { assets } from '$app/paths';
</script>
{#each content.blocks as block}
{#if block.Type === 'text'}
<!-- ... -->
{:else if block.type === 'photo'}
<FeaturePhoto
width={block.width}
src={`${assets}/${block.src}`}
altText={block.altText}
caption={block.caption}
/>
{/if}
{/each}
```
## Missing alt text
`altText` is required in this component. If your photo is missing it, a small red text box will overlay the image.
<Canvas of={FeaturePhotoStories.MissingAltText} />

View file

@ -1,26 +1,10 @@
<script module lang="ts">
import { defineMeta } from '@storybook/addon-svelte-csf';
// @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 missingAltTextDocs from './stories/docs/missingAltText.md?raw';
import { defineMeta } from '@storybook/addon-svelte-csf';
import FeaturePhoto from './FeaturePhoto.svelte';
// import {
// withComponentDocs,
// withStoryDocs,
// } from '$lib/docs/utils/withParams.js';
const { Story } = defineMeta({
title: 'Components/Multimedia/FeaturePhoto',
component: FeaturePhoto,
// ...withComponentDocs(componentDocs),
tags: ['autodocs'],
argTypes: {
width: {
control: 'select',
@ -35,38 +19,23 @@
</script>
<script>
// @ts-ignore jpg
import sharkSrc from './stories/shark.jpg';
import sharkSrc from './images/shark.jpg';
</script>
<Story
name="Default"
args="{{
name="Demo"
args={{
src: sharkSrc,
altText: 'A shark!',
width: 'normal',
caption: 'Carcharodon carcharias - REUTERS',
}}"
}}
/>
<Story
name="ArchieML"
args="{{
src: sharkSrc,
altText: 'A shark!',
width: 'normal',
caption: 'Carcharodon carcharias - REUTERS',
}}"
/>
<!-- {...withStoryDocs(archieMLDocs)} -->
<Story
name="Missing altText"
args="{{
exportName="MissingAltText"
args={{
src: sharkSrc,
width: 'normal',
caption: 'Carcharodon carcharias - REUTERS',
}}"
}}
/>
<!-- {...withStoryDocs(missingAltTextDocs)} -->

View file

@ -1,75 +1,89 @@
<!-- @migration-task Error while migrating Svelte code: Cannot set properties of undefined (setting 'next') -->
<!-- @component `FeaturePhoto` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-multimedia-featurephoto--docs) -->
<script lang="ts">
import { onMount } from 'svelte';
import Block from '../Block/Block.svelte';
import type { ContainerWidth } from '../@types/global';
import Block from '../Block/Block.svelte';
import PaddingReset from '../PaddingReset/PaddingReset.svelte';
/**
* Photo src
* @type {string}
* @required
*/
export let src: string;
/**
* Photo altText
* @type {string}
* @required
*/
export let altText: string;
/**
* Add an id to target with custom CSS.
* @type {string}
*/
export let id: string = '';
/**
* Add extra classes to target with custom CSS.
* @type {string}
*/
let cls: string = '';
export { cls as class };
/**
* Caption below the photo
* @type {string}
*/
export let caption: string;
/**
* Height of the photo placeholder when lazy-loading
*/
export let height: number = 100;
/**
* Width of the container, one of: normal, wide, wider, widest or fluid
*/
export let width: ContainerWidth = 'normal';
interface Props {
/**
* Photo source
*/
src: string;
/**
* Photo altText
*/
altText: string;
/**
* Add an id to target with custom CSS.
*/
id?: string;
/**
* Add classes to target with custom CSS.
*/
class?: string;
/**
* Photo caption
*/
caption?: string;
/**
* Height of the photo placeholder when lazy-loading
*/
height?: number;
/**
* Width of the container: normal, wide, wider, widest or fluid
*/
width?: ContainerWidth;
/**
* Set a different width for the text vs the photo. 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;
/**
* Whether to lazy load the photo using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)
*/
lazy?: boolean;
/**
* Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `top` when lazy loading.
*/
top?: number;
/**
* Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `bottom` when lazy loading.
*/
bottom?: number;
/**
* Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `left` when lazy loading.
*/
left?: number;
/**
* Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `right` when lazy loading.
*/
right?: number;
}
/**
* 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';
let {
src,
altText,
id = '',
class: cls = '',
caption,
height = 100,
width = 'normal',
textWidth = 'normal',
lazy = true,
top = 0,
bottom = 0,
left = 0,
right = 0,
}: Props = $props();
/**
* Whether to lazy load the photo using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)
*/
export let lazy: boolean = false;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `top` when lazy loading. */
export let top = 0;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `bottom` when lazy loading. */
export let bottom = 0;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `left` when lazy loading. */
export let left = 0;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `right` when lazy loading. */
export let right = 0;
let intersecting = false;
let container;
let intersecting = $state(false);
let container: HTMLElement;
const intersectable = typeof IntersectionObserver !== 'undefined';
onMount(() => {
if (!lazy) return;
if (intersectable) {
const rootMargin = `${bottom}px ${left}px ${top}px ${right}px`;
@ -93,18 +107,18 @@
<Block {width} class="photo fmy-6 {cls}" {id}>
<figure
bind:this="{container}"
bind:this={container}
aria-label="media"
class="w-full flex flex-col relative"
>
{#if !lazy || (intersectable && intersecting)}
<img class="w-full my-0" {src} alt="{altText}" />
<img class="w-full my-0" {src} alt={altText} />
{:else}
<div class="placeholder w-full" style="{`height: ${height}px;`}"></div>
<div class="placeholder w-full" style={`height: ${height}px;`}></div>
{/if}
{#if caption}
<PaddingReset containerIsFluid="{width === 'fluid'}">
<Block width="{textWidth}" class="notes w-full fmy-0">
<PaddingReset containerIsFluid={width === 'fluid'}>
<Block width={textWidth} class="notes w-full fmy-0">
<figcaption>
{caption}
</figcaption>

View file

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View file

@ -1,37 +0,0 @@
```yaml
[blocks]
type: photo
width: normal
src: images/shark.jpg
altText: The king of the sea
caption: Carcharodon carcharias - REUTERS
[]
```
```svelte
<!-- App.svelte -->
<script>
import { FeaturePhoto } from '@reuters-graphics/graphics-components';
import content from '$locales/en/content.json';
import { assets } from '$app/paths';
</script>
{#each content.blocks as block}
{#if block.Type === 'text'}
<!-- ... -->
{:else if block.type === 'photo'}
<FeaturePhoto
width="{block.width}"
src="{`${assets}/${block.src}`}"
altText="{block.altText}"
caption="{block.caption}"
/>
<!-- ... -->
{/if}
{/each}
```

View file

@ -1,16 +0,0 @@
A full-width photo inside the text well.
```svelte
<script>
import { FeaturePhoto } from '@reuters-graphics/graphics-components';
import { assets } from '$app/paths'; // 👈 If using in the Graphics Kit...
</script>
<FeaturePhoto
src="{`${assets}/images/myImage.jpg`}"
altText="Some alt text"
caption="A caption"
lazy="{false}"
width="normal"
/>
```

View file

@ -1 +0,0 @@
If your photo is missing `altText` a small warning will overlay the image.