delets Test, starts video migration

This commit is contained in:
MinamiFunakoshiTR 2025-03-26 11:53:24 -07:00
parent fd5df38dcf
commit eaa458a0fa
Failed to extract signature
15 changed files with 201 additions and 624 deletions

View file

@ -1,44 +0,0 @@
<script module lang="ts">
import TestForSvelte5 from './TestForSvelte5.svelte';
// Don't lose the "?raw" in markdown imports!
// @ts-ignore raw
import componentDocs from './stories/docs/component.md?raw';
import { withComponentDocs } from '$docs/utils/withParams.js';
export const meta = {
title: 'Components/Graphics/TestForSvelte5',
component: TestForSvelte5,
...withComponentDocs(componentDocs),
// https://storybook.js.org/docs/svelte/essentials/controls
argTypes: {
width: {
control: 'select',
options: ['normal', 'wide', 'wider', 'widest', 'fluid'],
},
},
};
</script>
<script lang="ts">
import { Template, Story } from '@storybook/addon-svelte-csf';
// 🖼️ You can import images you need in stories directly in code!
// @ts-ignore img
import SharkImg from './stories/shark.jpg';
</script>
<Template >
{#snippet children({ ...args })}
<TestForSvelte5 {...args} />
{/snippet}
</Template>
<Story
name="Default"
args="{{
width: 'normal',
src: SharkImg,
altText: "Duh dum! It's a shark!!",
}}"
/>

View file

@ -1,60 +0,0 @@
<!-- @migration-task Error while migrating Svelte code: Cannot set properties of undefined (setting 'next') -->
<!-- @component `TestForSvelte5` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-graphics-testforsvelte5--docs) -->
<script lang="ts">
/** ✏️ DOCUMENT your chart's props using TypeScript and JSDoc comments like below! */
/**
* A source for the image.
* @required
*/
export let src: string;
/**
* AltText for the image.
* @required
*/
export let altText: string;
/** Height of the image. */
export let height: number = 500;
// You can declare custom types to help users implement your component.
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
/** Width of the component within the text well. */
export let width: ContainerWidth = 'normal';
/** Add an ID to target with SCSS. */
export let id: string = '';
/** Add a class to target with SCSS. */
let cls: string = '';
export { cls as class };
import Block from '../Block/Block.svelte';
</script>
<Block {width} {id} class="photo {cls}">
<div
style:background-image="{`url(${src})`}"
style:height="{`${height}px`}"
></div>
<p class="visually-hidden">{altText}</p>
</Block>
<style lang="scss">
div {
width: 100%;
background-repeat: no-repeat;
background-size: cover;
}
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
</style>

View file

@ -1,23 +0,0 @@
> **Welcome to your new component!** Use this template to build your component and customise its storybook.
- Build your component in `TestForSvelte5/TestForSvelte5.svelte`.
- Write your component's storybook in `TestForSvelte5/TestForSvelte5.stories.svelte`.
- Don't forget to add your component to `src/index.js`:
```javascript
// ...
export { default as TestForSvelte5 } from './components/TestForSvelte5/TestForSvelte5.svelte';
```
- Commit your component to a new branch and push it to GitHub! 🏁
---
```html
<script>
import { TestForSvelte5 } from '@reuters-graphics/graphics-components';
</script>
<TestForSvelte5 />
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

View file

@ -0,0 +1,25 @@
import { Meta, Canvas } from '@storybook/blocks';
import * as VideoStories from './Video.stories.svelte';
<Meta of={VideoStories} />
# Video
The `Video` component adds video to your page. Can play on load or when the video comes into view and has play/pause controls. Supports videos with or without audio.
```svelte
<script>
import { Video } from '@reuters-graphics/graphics-components';
import { assets } from '$app/paths'; // If using local video in the Graphics Kit
</script>
<Video
ariaDescription={'Compulsory description of your video for screen readers.'}
src={`${assets}/videos/myVideo.mp4`}
width={'wide'}
caption={'Optional caption for your video.'}
/>
```
<Canvas of={VideoStories.Demo} />

View file

@ -1,55 +1,32 @@
<script module lang="ts">
// @ts-ignore raw
import componentDocs from './stories/docs/component.md?raw';
// @ts-ignore raw
import playAndLoopDocs from './stories/docs/playAndLoop.md?raw';
// @ts-ignore raw
import controlsDocs from './stories/docs/controls.md?raw';
// @ts-ignore raw
// import withSoundDocs from './stories/docs/withSound.md?raw';
import { defineMeta } from '@storybook/addon-svelte-csf';
import Video from './Video.svelte';
import {
withComponentDocs,
withStoryDocs,
} from '$lib/docs/utils/withParams.js';
export const meta = {
const { Story } = defineMeta({
title: 'Components/Multimedia/Video',
component: Video,
...withComponentDocs(componentDocs),
};
});
</script>
<script>
import { Template, Story } from '@storybook/addon-svelte-csf';
// @ts-ignore raw
import SilentVideo from './stories/videos/silent-video.mp4';
// @ts-ignore raw
import SoundVideo from './stories/videos/sound-video.mp4';
import SilentVideo from './demo/videos/silent-video.mp4';
import SoundVideo from './demo/videos/sound-video.mp4';
</script>
<Template >
{#snippet children({ args })}
<Video {...args} />
{/snippet}
</Template>
<Story
name="Default"
args="{{
name="Demo"
args={{
ariaDescription: 'Compulsory description of your video for screen readers.',
src: SilentVideo,
width: 'wide',
notes: 'Optional caption for your video.',
}}"
}}
/>
<Story
name="Playing and looping"
args="{{
exportName="PlayingAndLooping"
args={{
ariaDescription: 'Compulsory description of your video for screen readers.',
src: SilentVideo,
width: 'normal',
@ -57,13 +34,12 @@
notes:
"World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters",
playVideoThreshold: 0.9,
}}"
{...withStoryDocs(playAndLoopDocs)}
}}
/>
<Story
name="Controls"
args="{{
args={{
ariaDescription: 'Compulsory description of your video for screen readers.',
src: SilentVideo,
width: 'normal',
@ -76,13 +52,13 @@
separateReplayIcon: true,
loopVideo: false,
hoverToSeeControls: true,
}}"
{...withStoryDocs(controlsDocs)}
}}
/>
<Story
name="Videos with sound"
args="{{
exportName="WithSound"
args={{
ariaDescription: 'Compulsory description of your video for screen readers.',
src: SoundVideo,
width: 'normal',
@ -94,6 +70,5 @@
muteVideo: false,
playVideoWhenInView: true,
allowSoundToAutoplay: true,
}}"
{...withStoryDocs(controlsDocs)}
}}
/>

View file

@ -1,124 +1,114 @@
<!-- @migration-task Error while migrating Svelte code: Cannot set properties of undefined (setting 'next') -->
<!-- @component `Video` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-multimedia-video--docs) -->
<script lang="ts">
import IntersectionObserver from 'svelte-intersection-observer';
import Controls from './Controls.svelte';
import Controls from './components/Controls.svelte';
import GraphicBlock from '../GraphicBlock/GraphicBlock.svelte';
import type { ContainerWidth } from '../@types/global';
import type { Snippet } from 'svelte';
/// //////////////////////////////////
/// /////////// Props ////////////////
/// //////////////////////////////////
interface Props {
/** Video source */
src: string;
/** Image to be shown while the video is downloading */
poster?: string;
/** Whether to wrap the graphic with an aria hidden tag. */
hidden?: boolean;
/** ARIA description, passed in as a markdown string. */
ariaDescription?: string;
/** Add extra classes to the block tag to target it with custom CSS. */
class?: string;
/** Title of the graphic */
title?: string;
/** Notes to the graphic, passed in as a markdown string OR a custom snippet. */
notes: string | Snippet;
/** Description of the graphic, passed in as a markdown string. */
description?: string;
/** Width of the block within the article 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;
/** Preload options. `auto` is ignored if `autoplay` is true. Can also be `none` or `metadata`. */
preloadVideo?: 'auto' | 'none' | 'metadata';
/** Whether the video should loop. */
loopVideo?: boolean;
/** Whether video should have sound or not. */
muteVideo?: boolean;
/** If `true`, this allow videos with sound to autoplay if the user has previously interacted with DOM */
sountAutoplay?: boolean;
/** Whether the video should play when it comes into view or just on page load */
playVideoWhenInView?: boolean;
/** If video plays with intersection observer, how much of it should be into view to start playing */
playVideoThreshold?: number;
/** Whether to have the option to pause and play video */
possibleToPlayPause?: boolean;
/** Whether to show the play / pause buttons */
showControls?: boolean;
/** Whether you need to hover over the video to see the controls */
hoverToSeeControls?: boolean;
/** Whether to use a separate replay icon or use the play icon for replay as well */
separateReplayIcon?: boolean;
/** Change the colour of the play/pause button */
controlsColour?: string;
/** Change the opacity of the play/pause button */
controlsOpacity?: number;
/** Have four options for controls position - top right, top left, bottom right, bottom left */
controlsPosition?:
| 'top right'
| 'top left'
| 'bottom right'
| 'bottom left';
}
/**
* Video src
* @type {string}
* @required
*/
export let src: string;
/**
* Image to be shown while the video is downloading
*/
export let poster: string = '';
/**
* Whether to wrap the graphic with an aria hidden tag.
*/
export let hidden: boolean = true;
/**
* ARIA description, passed in as a markdown string.
* @type {string}
*/
export let ariaDescription: string | null = null;
/** Add extra classes to the block tag to target it with custom CSS. */
let cls: string = '';
export { cls as class };
/**
* Title of the graphic
* @type {string}
*/
export let title: string | null = null;
/**
* Notes to the graphic, passed in as a markdown string.
* @type {string}
*/
export let notes: string | null = null;
/**
* Description of the graphic, passed in as a markdown string.
* @type {string}
*/
export let description: string | null = null;
/**
* Width of the block within the article well.
* @type {string}
*/
export let width: ContainerWidth = 'normal';
type PreloadOptions = 'auto' | 'none' | 'metadata';
/**
* 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';
/**
* Preload options. `auto` is ignored if `autoplay` is true. Can also be `none` or `metadata`.
* @type {string}
*/
export let preloadVideo: PreloadOptions = 'auto';
/**
* Whether the video should loop.
*/
export let loopVideo: boolean = true;
/**
* Whether video should have sound or not.
*/
export let muteVideo: boolean = true;
export let allowSoundToAutoplay = false; // for video with sound, whether video should be allowed to autoplay if the user has previously interacted with DOM
export let playVideoWhenInView = true; // whether the video should play when it comes into view or just on page load
export let playVideoThreshold = 0.5; // if video plays with intersection observer, how much of it should be into view to start playing
export let possibleToPlayPause = true; // whether to have the option to pause and play video
export let showControls = true; // whetner to show the play / pause buttons
export let hoverToSeeControls = false; // whether you need to hover over the video to see the controls
export let separateReplayIcon = false; // whether to use a separate replay icon or use the play icon for replay as well
export let controlsColour = '#333'; // change the colour of the play/pause button
export let controlsOpacity = 0.5; // change the opacity of the play/pause button
$: interactiveControlsOpacity = 0;
export let controlsPosition = 'top left'; // have four options for controls position - top right, top left, bottom right, bottom left
let {
src,
poster = '',
hidden = true,
ariaDescription,
class: cls = '',
title,
notes,
description,
width = 'normal',
textWidth = 'normal',
preloadVideo = 'auto',
loopVideo = false,
muteVideo = true,
sountAutoplay = false,
playVideoWhenInView = true,
playVideoThreshold = 0.5,
possibleToPlayPause = true,
showControls = true,
hoverToSeeControls = false,
separateReplayIcon = false,
controlsColour = '#333',
controlsOpacity = 0.5,
controlsPosition = 'top left',
}: Props = $props();
/// //////////////////////////////////
/// /////// Internal Logic ///////////
/// //////////////////////////////////
// If it's not possible to play/pause, then hide the controls
if (!possibleToPlayPause) showControls = false;
// Internal props
let time = 0;
let duration;
let paused = true;
let clickedOnPauseBtn = false; // special variable to track if user clicked on 'pause' btn to help with audio logic
$: resetCondition = time >= duration; // - 0.1;
let time = $state(0);
let duration = $state(0);
let paused = $state(true);
let clickedOnPauseBtn = $state(false); // special variable to track if user clicked on 'pause' btn to help with audio logic
let resetCondition = $derived(time >= duration); // - 0.1;
// Dimensions etc other useful things
let heightVideo;
let widthVideo;
let heightVideoContainer;
let widthVideoContainer;
let heightVideo = $state(0);
let widthVideo = $state(0);
let heightVideoContainer = $state(0);
let widthVideoContainer = $state(0);
const controlsBorderOffset = 50;
// For intersection observer
let intersecting;
let element;
let videoElement;
let intersecting = $state(false);
let element: HTMLElement = $state(new HTMLElement()); // ; | null
let videoElement: HTMLVideoElement = $state(new HTMLVideoElement());
// For video with sound, check if there has been an interaction with the DOM
let interactedWithDom = false;
@ -126,27 +116,29 @@
interactedWithDom = true;
};
// Play the video (with no sound) if it's intersecting; pause when it's no longer intersecting
$: if (playVideoWhenInView && intersecting && muteVideo) paused = false;
$: if (playVideoWhenInView && !intersecting) paused = true;
// Special case for video with sound
// Only ff you've clicked on play button or interacted with DOM in any way previously, video with audio will play
$: if (
allowSoundToAutoplay &&
playVideoWhenInView &&
intersecting &&
!muteVideo &&
interactedWithDom &&
!clickedOnPauseBtn // so video doesn't autoplay when coming into view again if paused previously
) {
paused = false;
}
let interactiveControlsOpacity = $state(controlsOpacity);
$: if (allowSoundToAutoplay && !muteVideo && !interactedWithDom) {
paused = true;
}
$effect(() => {
// Play the video (with no sound) if it's intersecting; pause when it's no longer intersecting
if (playVideoWhenInView && intersecting && muteVideo) paused = false;
$: if (!possibleToPlayPause) showControls = true;
// Pause the video if it's no longer intersecting
if (playVideoWhenInView && !intersecting) paused = true;
// Special case for video with sound
// Only ff you've clicked on play button or interacted with DOM in any way previously, video with audio will play
if (
sountAutoplay &&
playVideoWhenInView &&
intersecting &&
!muteVideo &&
interactedWithDom &&
!clickedOnPauseBtn // so video doesn't autoplay when coming into view again if paused previously
)
paused = false;
if (sountAutoplay && !muteVideo && !interactedWithDom) paused = true;
});
// To get the pause state passed up from the Controls
const pausePlayEvent = (e) => {
@ -165,32 +157,32 @@
</script>
<svelte:window
on:click="{setInteractedWithDom}"
on:touchstart="{setInteractedWithDom}"
on:click={setInteractedWithDom}
on:touchstart={setInteractedWithDom}
/>
<GraphicBlock
{textWidth}
{title}
{description}
{notes}
notes={typeof notes === 'string' ? notes : null}
{width}
class="video {cls}"
>
<div
role="figure"
on:mouseover="{() => {
onmouseover={() => {
interactiveControlsOpacity = controlsOpacity;
}}"
on:focus="{() => {
}}
onfocus={() => {
interactiveControlsOpacity = controlsOpacity;
}}"
on:mouseout="{() => {
}}
onmouseout={() => {
interactiveControlsOpacity = 0;
}}"
on:blur="{() => {
}}
onblur={() => {
interactiveControlsOpacity = 0;
}}"
}}
>
{#if (hidden && ariaDescription) || !hidden}
{#if ariaDescription}
@ -202,25 +194,25 @@
<IntersectionObserver
{element}
bind:intersecting
threshold="{playVideoThreshold}"
once="{false}"
threshold={playVideoThreshold}
once={false}
>
<div
bind:this="{element}"
bind:this={element}
class="video-wrapper relative block"
aria-hidden="{hidden}"
bind:clientWidth="{widthVideoContainer}"
bind:clientHeight="{heightVideoContainer}"
aria-hidden={hidden}
bind:clientWidth={widthVideoContainer}
bind:clientHeight={heightVideoContainer}
>
{#if possibleToPlayPause}
{#if showControls}
<Controls
on:pausePlayEvent="{pausePlayEvent}"
on:pausePlayEvent={pausePlayEvent}
{paused}
{clickedOnPauseBtn}
controlsOpacity="{hoverToSeeControls ?
controlsOpacity={hoverToSeeControls ?
interactiveControlsOpacity
: controlsOpacity}"
: controlsOpacity}
{controlsPosition}
{widthVideoContainer}
{heightVideoContainer}
@ -232,32 +224,33 @@
{:else}
<button
class="border-0 m-0 p-0 bg-transparent absolute"
on:click="{() => {
aria-label="Play or pause video"
onclick={() => {
if (paused === true) {
paused = false;
} else {
paused = true;
}
}}"
}}
style="top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
></button>
{/if}
{/if}
<video
bind:this="{videoElement}"
bind:this={videoElement}
{src}
{poster}
class="pointer-events-none relative"
width="100%"
muted="{muteVideo}"
muted={muteVideo}
playsinline
preload="{preloadVideo}"
loop="{loopVideo}"
bind:currentTime="{time}"
preload={preloadVideo}
loop={loopVideo}
bind:currentTime={time}
bind:duration
bind:paused
bind:clientWidth="{widthVideo}"
bind:clientHeight="{heightVideo}"
bind:clientWidth={widthVideo}
bind:clientHeight={heightVideo}
>
<track kind="captions" />
</video>
@ -267,14 +260,14 @@
<!-- Video element without Intersection observer -->
<div
class="video-wrapper relative"
aria-hidden="{hidden}"
bind:clientWidth="{widthVideoContainer}"
bind:clientHeight="{heightVideoContainer}"
aria-hidden={hidden}
bind:clientWidth={widthVideoContainer}
bind:clientHeight={heightVideoContainer}
>
{#if possibleToPlayPause}
{#if showControls}
<Controls
on:pausePlayEvent="{pausePlayEvent}"
on:pausePlayEvent={pausePlayEvent}
{paused}
{clickedOnPauseBtn}
{controlsOpacity}
@ -289,33 +282,34 @@
{:else}
<button
class="border-0 m-0 p-0 bg-transparent absolute"
on:click="{() => {
aria-label="Play or pause video"
onclick={() => {
if (paused === true) {
paused = false;
} else {
paused = true;
}
}}"
}}
style="top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
></button>
{/if}
{/if}
<video
bind:this="{videoElement}"
bind:this={videoElement}
{src}
{poster}
class="pointer-events-none relative"
width="100%"
muted="{muteVideo}"
muted={muteVideo}
playsinline
preload="{preloadVideo}"
loop="{loopVideo}"
bind:currentTime="{time}"
preload={preloadVideo}
loop={loopVideo}
bind:currentTime={time}
bind:duration
bind:paused
autoplay
bind:clientWidth="{widthVideo}"
bind:clientHeight="{heightVideo}"
bind:clientWidth={widthVideo}
bind:clientHeight={heightVideo}
>
<track kind="captions" />
</video>
@ -323,7 +317,7 @@
{/if}
{/if}
</div>
{#if $$slots.notes}
{#if notes}
<!-- Custom notes and source slot -->
<slot name="notes" />
{/if}

View file

@ -1,275 +0,0 @@
---
title: Video
description: General-purpose video component. Can play on load or when the video comes into view and has play/pause controls. Supports videos with or without audio.
slug: video
---
<script>
import {assets} from '$app/paths'; import Video from './index.svelte'; import
DemoContainer from '../_docs/DemoContainer/index.svelte';
</script>
<section>
## {title}
{description}
</section>
```svelte
<script>
import { assets } from '$app/paths'; // helper if importing video from 'statics'
import { Video } from '@reuters-graphics/graphics-svelte-components';
</script>
<Video ariaDescription={"Compulsory description of your video for screen
readers."} src={`${assets}/videos/myVideo.mp4`} // or a URL to an external video
width={'wide'} // normal, wide, wider, widest or fluid caption={'Optional
caption for your video.'} />
```
<DemoContainer>
<Video
ariaDescription="Description of your video for screen readers."
src={`${assets}/videos/Sequence silent video_4.mp4`}
width="wide"
caption="World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters"
/>
</DemoContainer>
<section>
#### When to play and whether to loop
`playVideoWhenInView`, `playVideoThreshold`
- By default, the video will **start playing when 50% of the video element's height is visible on the page**.
To control the threshold of visibility at which the video starts playing, add the prop `playVideoThreshold` and set it to a value between 0 and 1,
where 0 means that the video will start playing as soon as its top enters the viewport, while 1 means it will start when the whole video is in the viewport.
- If you don't want the video to play when you scroll to it, but **on page load**, add the prop `playVideoWhenInView={false}`. The default of the prop is `true`,
which corresponds to the behaviour described above.
`loopVideo`
- By default, the video will **loop**. If you don't want that, add the prop `loopVideo={false}`.
Here is an example of what the same video would look like with a visibility threshold of 0.9 and not looping. Scroll down slowly to observe the behaviour.
</section>
```svelte
<script>
import { Video } from '@reuters-graphics/graphics-svelte-components';
</script>
<video
ariaDescription="{'Compulsory description of your video for screen readers.'}"
src="{'path-to-video-or-external-url'}"
width="{'normal'}"
loopVideo="{false}"
playVideoThreshold="{0.9}"></video>
```
<DemoContainer>
<Video
ariaDescription="Description of your video for screen readers."
src={`${assets}/videos/Sequence silent video_4.mp4`}
width="normal"
caption="World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters"
loopVideo={false}
playVideoThreshold={0.9}
/>
</DemoContainer>
<section>
#### Controls (play / pause)
`showControls`
- By default, the video has a play/pause button, which corresponds to
`showControls={true}`. If you don't want these, just set `showControls={false}`.
When you do that, the icons themselves will disappear but the functionality of playing and pausing remains and can be done by clicking on the video itself.
If you don't want to enable any play/pause functionality, add `possibleToPlayPause={false}`.
- If you want to show the controls only when the video is hovered, set `hoverToSeeControls={true}`.
`controlsColour`, `controlsOpacity`, `controlsPosition`, `separateReplayIcon`
If you do want to leave the controls, you have a couple of options to style them:
- Set `controlsColour` to a colour of your choosing.
- Set `controlsOpacity` to a value between `0` and `1` to control the opacity. The default is `0.5`.
- Change the placement of the controls to one of: `top right`, `top left`, `bottom right`, `bottom left` by setting `controlsPosition`.
- Change the play button to a replay button at the end of the video with the option `separateReplayIcon={true}`.
Here is an example with bottom right corner white opaque controls, with a replay button, where you have to hover on the video to see the controls.
</section>
```svelte
<script>
import { Video } from '@reuters-graphics/graphics-svelte-components';
</script>
<Video ariaDescription={"Compulsory description of your video for screen
readers."} src={'path-to-video-or-external-url'} size={'normal'}
caption={'Optional caption for your video.'} playVideoThreshold={0.1}
controlsColour={'white'} controlsOpacity={1} controlsPosition={'bottom right'}
separateReplayIcon={true} loopVideo={false} // If you don't set loopVideo to
false, you won't see the loop button hoverToSeeControls={true} />
```
<DemoContainer>
<Video
ariaDescription="Description of your video for screen readers."
src={`${assets}/videos/Sequence silent video_4.mp4`}
size="normal"
caption="World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters"
playVideoThreshold={0.1}
controlsColour={'white'}
controlsOpacity={1}
controlsPosition={'bottom right'}
separateReplayIcon={true}
loopVideo={false}
hoverToSeeControls={true}
/>
</DemoContainer>
<section>
#### Videos with sound
If you've ever had to put sound on a page in recent years,
you'll know that auto-playing sound is not allowed by browsers. The user will need to interact with the page first, and it will depend on your
particular use case how and when you'd like this to happen. This component provides two options to deal with this.
If you have a video with sound, make sure to add the prop `muteVideo={false}`.
Then you can either:
- `allowSoundToAutoplay={false}` (default) : Don't allow the video to autoplay under any circumstances other than when the user clicks the 'play' on the video. Note that this
works whether or not you have the controls visible, i.e. with `showControls` being `true` or `false`, as long as you allow
play/pause behaviour with `possibleToPlayPause={true}` (default).
- `allowSoundToAutoplay={true}` : Allow the video to autoplay when it comes into view as long as the user has interacted with the page preivously, i.e. they have clicked/tapped
anywhere on the page.
You should keep `playVideoWhenInView={true}` (default). There is no option to autoplay video with sound when the user clicks on the page
elsewhere if the video is not in view. In other words, you can't start playing sound for a video which is not in view with this component.
This is probably not a behaviour you'd want anyway.
The example below allows for autoplay if the user has interacted with the page before the video comes into view. To see this, reload the page
and go to the top. Click anywhere on the page before scrolling down to the video and you should see it autoplay when it comes into view.
</section>
```svelte
<script>
import { Video } from '@reuters-graphics/graphics-svelte-components';
</script>
<video
ariaDescription="{'Compulsory description of your video for screen readers.'}"
src="{'path-to-video-or-external-url'}"
width="{'normal'}"
controlsOpacity="{1}"
loopVideo="{false}"
muteVideo="{false}"
allowSoundToAutoplay="{true}"></video>
```
<DemoContainer>
<Video
ariaDescription="Description of your video for screen readers."
src={`${assets}/videos/Sequence sound video.mp4`}
width="normal"
caption="World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters"
controlsOpacity={1}
loopVideo={false}
muteVideo={false}
playVideoWhenInView={true}
showControls={true}
allowSoundToAutoplay={true}
/>
</DemoContainer>
<section>
### All the props
Here is a list of all the props that you can pass to the component for reference. Most of them are discussed above.
##### Required
- **src** (string) - Path to the video relative to the `statics` folder.
- **ariaDescription** (string) and **ariaHidden** (bool) - Either write a description for screen readers in ariaDescription or set ariaHidden to false.
##### Optional
- **caption** (string) - default <span class='default'>**" " (none)**</span> <span class='separator'></span> options: Write a caption to go with the video.
- **size** (string) - default <span class='default'>**'normal'**</span> <span class='separator'></span> options: _'normal'_, _'wide'_, _'wider'_, _'widest'_, _'fluid'_
- **preloadVideo** (string) - default <span class='default'>**'auto'**</span> <span class='separator'></span>
options: _'none'_ (Don't preload the video on page load),
_'auto'_ (Preload the video),
_'metadata'_ (Only preload the metadata)
- **loopVideo** (bool) - default <span class='default'>**true**</span> <span class='separator'></span> options: _true_, _false_
- **muteVideo** (bool) - default <span class='default'>**true**</span> <span class='separator'></span> options: _true_, _false_
- **allowSoundToAutoplay** (bool) - default <span class='default'>**false**</span><span class='separator'></span> options: _true_, _false_.
For video with sound, whether video should be allowed to autoplay if the user has previously interacted with DOM. You need to set `muteVideo` to `true`
for this to work.
- **playVideoWhenInView** (bool) - default <span class='default'>**true**</span> <span class='separator'></span>
options: _true_ (Only start playing the video when it comes into view), _false_ (Start playing as soon as the page and video load)
- **playVideoThreshold** (float) - default <span class='default'>**0.5**</span> <span class='separator'></span> options: _float between 0 and 1_.
How much of the video should be into view to start playing when playVideoWhenInView is true.
- **possibleToPlayPause** (bool) - default <span class='default'>**true**</span> <span class='separator'></span> options: _true_, _false_
- **showControls** (bool) - default <span class='default'>**true**</span> <span class='separator'></span> options: _true_, _false_.
Whether to show the play/pause controls or not.
- **hoverToSeeControls** (bool) - default <span class='default'>**false**</span><span class='separator'></span> options: _true_, _false_.
Whether you need to hover over the video to see the controls.
- **separateReplayIcon** (bool) - default <span class='default'>**false**</span> <span class='separator'></span> options: _true_, _false_.
Whether to use a separate replay icon or use the play icon for replay as well.
- **controlsColour** (colour string) - default <span class='default'>**'#333'**</span> <span class='separator'></span> options: _any valid colour string_.
Controls the colour of the play/pause buttons.
- **controlsOpacity** (float) - default <span class='default'>**0.5**</span> <span class='separator'></span> options: _float between 0 and 1_.
Controls the opacity of the play/pause buttons.
- **controlsPosition** (string) - default <span class='default'>**'top left'**</span> <span class='separator'></span>
options: _'top right'_, _'top left'_, _'bottom right'_, _'bottom left'_.
Controls the position of the play/pause buttons.
</section>
<style>
ul {
list-style-type: none;
}
li {
font-size: 1.2rem;
}
.default {
color: #006d77;
}
.separator {
display: inline-block;
width: 5px;
height: 5px;
background-color: #666;
border-radius: 50%;
margin: 0 5px 0 5px;
transform: translateY(-2.5px);
}
</style>

View file

@ -1,15 +0,0 @@
General-purpose video component. Can play on load or when the video comes into view and has play/pause controls. Supports videos with or without audio.
```svelte
<script>
import { Video } from '@reuters-graphics/graphics-components';
import { assets } from '$app/paths'; // If using local video in the Graphics Kit
</script>
<Video
ariaDescription="{'Compulsory description of your video for screen readers.'}"
src="{`${assets}/videos/myVideo.mp4`}"
width="{'wide'}"
caption="{'Optional caption for your video.'}"
/>
```