video
This commit is contained in:
parent
6db53c3944
commit
d9def09527
25 changed files with 455 additions and 457910 deletions
|
|
@ -40,6 +40,10 @@ p.sbdocs-p, ul.sbdocs-ul, li.sbdocs-li {
|
|||
@include font-display;
|
||||
}
|
||||
|
||||
.sbdocs {
|
||||
@include font-display;
|
||||
}
|
||||
|
||||
// .sbdocs {
|
||||
// max-width: 800px;
|
||||
// margin: 0 auto !important;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
</Template>
|
||||
|
||||
<Story
|
||||
name="Basic"
|
||||
name="Default"
|
||||
args="{{
|
||||
embedded: false,
|
||||
id: '',
|
||||
|
|
@ -113,7 +113,7 @@
|
|||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 5px;
|
||||
color: white;
|
||||
color: #666;
|
||||
}
|
||||
.padding-label {
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ The `Article` component contains all the content of our story and also establish
|
|||
|
||||
```svelte
|
||||
<script>
|
||||
import { Article } from '@reuters-graphics/graphics-svelte-components';
|
||||
import { Article } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<Article>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ A before and after image comparison component.
|
|||
|
||||
```svelte
|
||||
<script>
|
||||
import { BeforeAfter } from '@reuters-graphics/graphics-svelte-components';
|
||||
import { BeforeAfter } from '@reuters-graphics/graphics-components';
|
||||
import { assets } from '$app/paths'; // If using in the Graphics Kit
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
</Template>
|
||||
|
||||
<Story
|
||||
name="Basic"
|
||||
name="Default"
|
||||
args="{{
|
||||
width: 'normal',
|
||||
}}"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
The `Block` component is the basic building block of stories, a responsive container that wraps each section of your piece.
|
||||
|
||||
Blocks are stacked vertically within the well created by the `Article` component. They can have different widths on larger screens depending on the `width` prop.
|
||||
Blocks are stacked vertically within the well created by the [`Article`](./?path=/docs/layout-article) component. They can have different widths on larger screens depending on the `width` prop.
|
||||
|
||||
> 📌 Many of our other components already use the `Block` component, internally. You'll usually only need to use it yourself if you're making something custom.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Our article well is designed to provide a basic responsive layout issues for you, but it's also made to get out of the way quickly when you need to do something custom.
|
||||
Our article well is designed to provide a basic responsive layout for you, but it's also made to get out of the way quickly when you need to do something custom.
|
||||
|
||||
If you need to get really radical, the easiest way is to create a `Block` with a `fluid` width -- which basically cancels out the article well dimensions -- and then code whatever you need from scratch or with another framework.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
Body text includes the main text of your page.
|
||||
The `BodyText` creates the main text of your page. You can pass the `text` prop a [markdown-formatted](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) string, which will be parsed into paragraphs, headers, lists, blockquotes or whatever else you need.
|
||||
|
||||
Use it like this:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
|
|
@ -14,6 +16,8 @@ Body text includes the main text of your page.
|
|||
<BodyText text="{markdownText}" />
|
||||
```
|
||||
|
||||
... or more commonly, you'll use it with a Google doc in the Graphics Kit like this:
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { BodyText } from '@reuters-graphics/graphics-components';
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
import PlaceholderImg from './stories/placeholder.png';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/GraphicBlock',
|
||||
title: 'Layout/GraphicBlock',
|
||||
component: GraphicBlock,
|
||||
...withComponentDocs(componentDocs),
|
||||
// https://storybook.js.org/docs/svelte/essentials/controls
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
</Template>
|
||||
|
||||
<Story
|
||||
name="Basic"
|
||||
name="Default"
|
||||
args="{{
|
||||
width: 'normal',
|
||||
title: 'Bacon ipsum dolor amet t-bone',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
The `GraphicBlock` component is a more specific type of `Block` that handles text elements around your chart.
|
||||
The `GraphicBlock` component is a subset 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:
|
||||
|
||||
|
|
|
|||
97
src/components/Video/Video.stories.svelte
Normal file
97
src/components/Video/Video.stories.svelte
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<script>
|
||||
import { Meta, Template, Story } from '@storybook/addon-svelte-csf';
|
||||
|
||||
// @ts-ignore
|
||||
import componentDocs from './stories/docs/component.md?raw';
|
||||
// @ts-ignore
|
||||
import playAndLoopDocs from './stories/docs/playAndLoop.md?raw';
|
||||
// @ts-ignore
|
||||
import controlsDocs from './stories/docs/controls.md?raw';
|
||||
// @ts-ignore
|
||||
import withSoundDocs from './stories/docs/withSound.md?raw';
|
||||
|
||||
// @ts-ignore
|
||||
import SilentVideo from './stories/videos/silent-video.mp4';
|
||||
// @ts-ignore
|
||||
import SoundVideo from './stories/videos/sound-video.mp4';
|
||||
|
||||
import Video from './Video.svelte';
|
||||
|
||||
import {
|
||||
withComponentDocs,
|
||||
withStoryDocs
|
||||
} from '$lib/docs/utils/withParams.js';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Video',
|
||||
component: Video,
|
||||
...withComponentDocs(componentDocs),
|
||||
};
|
||||
</script>
|
||||
|
||||
<Meta {...meta} />
|
||||
|
||||
<Template let:args>
|
||||
<Video {...args} />
|
||||
</Template>
|
||||
|
||||
|
||||
|
||||
|
||||
<Story
|
||||
name="Default"
|
||||
args={{
|
||||
ariaDescription: "Compulsory description of your video for screen readers.",
|
||||
src: SilentVideo,
|
||||
width: 'wide',
|
||||
caption: 'Optional caption for your video.',
|
||||
}}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Playing and looping"
|
||||
args={{
|
||||
ariaDescription: "Compulsory description of your video for screen readers.",
|
||||
src: SilentVideo,
|
||||
width: 'normal',
|
||||
loopVideo: true,
|
||||
caption: 'World\'s longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters',
|
||||
playVideoThreshold: 0.9,
|
||||
}}
|
||||
{...withStoryDocs(playAndLoopDocs)}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Controls"
|
||||
args={{
|
||||
ariaDescription: "Compulsory description of your video for screen readers.",
|
||||
src: SilentVideo,
|
||||
width: 'normal',
|
||||
caption: 'World\'s longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters',
|
||||
playVideoThreshold: 0.9,
|
||||
controlsColour: 'white',
|
||||
controlsOpacity: 1,
|
||||
controlsPosition: 'bottom right',
|
||||
separateReplayIcon: true,
|
||||
loopVideo: false,
|
||||
hoverToSeeControls: true,
|
||||
}}
|
||||
{...withStoryDocs(controlsDocs)}
|
||||
/>
|
||||
|
||||
<Story
|
||||
name="Videos with sound"
|
||||
args={{
|
||||
ariaDescription: "Compulsory description of your video for screen readers.",
|
||||
src: SoundVideo,
|
||||
width: 'normal',
|
||||
caption: 'World\'s longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters',
|
||||
playVideoThreshold: 0.9,
|
||||
showControls: true,
|
||||
loopVideo: false,
|
||||
muteVideo: false,
|
||||
playVideoWhenInView: true,
|
||||
allowSoundToAutoplay: true,
|
||||
}}
|
||||
{...withStoryDocs(controlsDocs)}
|
||||
/>
|
||||
|
|
@ -1,20 +1,43 @@
|
|||
<script>
|
||||
<script lang="ts">
|
||||
import IntersectionObserver from 'svelte-intersection-observer';
|
||||
import Controls from './Controls.svelte';
|
||||
import Block from '../Block/Block.svelte';
|
||||
|
||||
/// //////////////////////////////////
|
||||
/// /////////// Props ////////////////
|
||||
/// //////////////////////////////////
|
||||
|
||||
/**
|
||||
* Video src.
|
||||
*/
|
||||
export let src = '';
|
||||
export let ariaHidden = true;
|
||||
export let ariaDescription = null;
|
||||
export let caption = '';
|
||||
|
||||
export let size = 'normal'; // normal, wide, wider, widest or fluid
|
||||
export let preloadVideo = 'auto'; // preload the video by default; this is ignored if autoplay is true; can also be none or metadata
|
||||
export let loopVideo = true; // whether the video should loop
|
||||
type ColumnWidth = 'narrower' | 'narrow' | 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
|
||||
|
||||
/**
|
||||
* Width of the block within the article well.
|
||||
* @type {string}
|
||||
*/
|
||||
export let width: ColumnWidth = 'normal';
|
||||
|
||||
export let muteVideo = true; // whther video should have sound or not
|
||||
type PreloadOptions = 'auto' | 'none' | 'metadata';
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
@ -100,36 +123,89 @@
|
|||
on:touchstart="{setInteractedWithDom}"
|
||||
/>
|
||||
|
||||
<section
|
||||
class="video-container graphic {size}"
|
||||
on:mouseover="{() => {
|
||||
interactiveControlsOpacity = controlsOpacity;
|
||||
}}"
|
||||
on:focus="{() => {
|
||||
interactiveControlsOpacity = controlsOpacity;
|
||||
}}"
|
||||
on:mouseout="{() => {
|
||||
interactiveControlsOpacity = 0;
|
||||
}}"
|
||||
on:blur="{() => {
|
||||
interactiveControlsOpacity = 0;
|
||||
}}"
|
||||
>
|
||||
{#if (ariaHidden && ariaDescription) || !ariaHidden}
|
||||
{#if ariaDescription}
|
||||
<p class="visually-hidden">{ariaDescription}</p>
|
||||
{/if}
|
||||
<Block {width} cls="video-container">
|
||||
<div
|
||||
on:mouseover="{() => {
|
||||
interactiveControlsOpacity = controlsOpacity;
|
||||
}}"
|
||||
on:focus="{() => {
|
||||
interactiveControlsOpacity = controlsOpacity;
|
||||
}}"
|
||||
on:mouseout="{() => {
|
||||
interactiveControlsOpacity = 0;
|
||||
}}"
|
||||
on:blur="{() => {
|
||||
interactiveControlsOpacity = 0;
|
||||
}}"
|
||||
>
|
||||
{#if (ariaHidden && ariaDescription) || !ariaHidden}
|
||||
{#if ariaDescription}
|
||||
<p class="visually-hidden">{ariaDescription}</p>
|
||||
{/if}
|
||||
|
||||
{#if playVideoWhenInView}
|
||||
<!-- Video element with Intersection Observer -->
|
||||
<IntersectionObserver
|
||||
element="{element}"
|
||||
bind:intersecting
|
||||
threshold="{playVideoThreshold}"
|
||||
once="{false}"
|
||||
>
|
||||
{#if playVideoWhenInView}
|
||||
<!-- Video element with Intersection Observer -->
|
||||
<IntersectionObserver
|
||||
element="{element}"
|
||||
bind:intersecting
|
||||
threshold="{playVideoThreshold}"
|
||||
once="{false}"
|
||||
>
|
||||
<div
|
||||
bind:this="{element}"
|
||||
class="video-wrapper"
|
||||
aria-hidden="{ariaHidden}"
|
||||
bind:clientWidth="{widthVideoContainer}"
|
||||
bind:clientHeight="{heightVideoContainer}"
|
||||
>
|
||||
{#if possibleToPlayPause}
|
||||
{#if showControls}
|
||||
<Controls
|
||||
on:pausePlayEvent="{pausePlayEvent}"
|
||||
paused="{paused}"
|
||||
clickedOnPauseBtn="{clickedOnPauseBtn}"
|
||||
controlsOpacity="{hoverToSeeControls
|
||||
? interactiveControlsOpacity
|
||||
: controlsOpacity}"
|
||||
controlsPosition="{controlsPosition}"
|
||||
widthVideoContainer="{widthVideoContainer}"
|
||||
heightVideoContainer="{heightVideoContainer}"
|
||||
controlsBorderOffset="{controlsBorderOffset}"
|
||||
resetCondition="{resetCondition}"
|
||||
separateReplayIcon="{separateReplayIcon}"
|
||||
controlsColour="{controlsColour}"
|
||||
/>
|
||||
{:else}
|
||||
<button
|
||||
on:click="{() => {
|
||||
paused === true ? (paused = false) : (paused = true);
|
||||
}}"
|
||||
style="position: absolute; top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
|
||||
></button>
|
||||
{/if}
|
||||
{/if}
|
||||
<video
|
||||
bind:this="{videoElement}"
|
||||
src="{src}"
|
||||
width="100%"
|
||||
muted="{muteVideo}"
|
||||
playsinline
|
||||
preload="{preloadVideo}"
|
||||
loop="{loopVideo}"
|
||||
bind:currentTime="{time}"
|
||||
bind:duration
|
||||
bind:paused
|
||||
bind:clientWidth="{widthVideo}"
|
||||
bind:clientHeight="{heightVideo}"
|
||||
style="{showControls ? 'position: relative' : 'position: relative'}"
|
||||
>
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
</div>
|
||||
</IntersectionObserver>
|
||||
{:else}
|
||||
<!-- Video element without Intersection observer -->
|
||||
<div
|
||||
bind:this="{element}"
|
||||
class="video-wrapper"
|
||||
aria-hidden="{ariaHidden}"
|
||||
bind:clientWidth="{widthVideoContainer}"
|
||||
|
|
@ -141,9 +217,7 @@
|
|||
on:pausePlayEvent="{pausePlayEvent}"
|
||||
paused="{paused}"
|
||||
clickedOnPauseBtn="{clickedOnPauseBtn}"
|
||||
controlsOpacity="{hoverToSeeControls
|
||||
? interactiveControlsOpacity
|
||||
: controlsOpacity}"
|
||||
controlsOpacity="{controlsOpacity}"
|
||||
controlsPosition="{controlsPosition}"
|
||||
widthVideoContainer="{widthVideoContainer}"
|
||||
heightVideoContainer="{heightVideoContainer}"
|
||||
|
|
@ -172,6 +246,7 @@
|
|||
bind:currentTime="{time}"
|
||||
bind:duration
|
||||
bind:paused
|
||||
autoplay
|
||||
bind:clientWidth="{widthVideo}"
|
||||
bind:clientHeight="{heightVideo}"
|
||||
style="{showControls ? 'position: relative' : 'position: relative'}"
|
||||
|
|
@ -179,64 +254,13 @@
|
|||
<track kind="captions" />
|
||||
</video>
|
||||
</div>
|
||||
</IntersectionObserver>
|
||||
{:else}
|
||||
<!-- Video element without Intersection observer -->
|
||||
<div
|
||||
class="video-wrapper"
|
||||
aria-hidden="{ariaHidden}"
|
||||
bind:clientWidth="{widthVideoContainer}"
|
||||
bind:clientHeight="{heightVideoContainer}"
|
||||
>
|
||||
{#if possibleToPlayPause}
|
||||
{#if showControls}
|
||||
<Controls
|
||||
on:pausePlayEvent="{pausePlayEvent}"
|
||||
paused="{paused}"
|
||||
clickedOnPauseBtn="{clickedOnPauseBtn}"
|
||||
controlsOpacity="{controlsOpacity}"
|
||||
controlsPosition="{controlsPosition}"
|
||||
widthVideoContainer="{widthVideoContainer}"
|
||||
heightVideoContainer="{heightVideoContainer}"
|
||||
controlsBorderOffset="{controlsBorderOffset}"
|
||||
resetCondition="{resetCondition}"
|
||||
separateReplayIcon="{separateReplayIcon}"
|
||||
controlsColour="{controlsColour}"
|
||||
/>
|
||||
{:else}
|
||||
<button
|
||||
on:click="{() => {
|
||||
paused === true ? (paused = false) : (paused = true);
|
||||
}}"
|
||||
style="position: absolute; top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
|
||||
></button>
|
||||
{/if}
|
||||
{/if}
|
||||
<video
|
||||
bind:this="{videoElement}"
|
||||
src="{src}"
|
||||
width="100%"
|
||||
muted="{muteVideo}"
|
||||
playsinline
|
||||
preload="{preloadVideo}"
|
||||
loop="{loopVideo}"
|
||||
bind:currentTime="{time}"
|
||||
bind:duration
|
||||
bind:paused
|
||||
autoplay
|
||||
bind:clientWidth="{widthVideo}"
|
||||
bind:clientHeight="{heightVideo}"
|
||||
style="{showControls ? 'position: relative' : 'position: relative'}"
|
||||
>
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
</div>
|
||||
{/if}
|
||||
{#if caption}
|
||||
<figcaption>{caption}</figcaption>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if caption}
|
||||
<figcaption>{caption}</figcaption>
|
||||
{/if}
|
||||
{/if}
|
||||
</section>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<style lang="scss">
|
||||
.video-wrapper {
|
||||
|
|
@ -5,9 +5,8 @@ slug: video
|
|||
---
|
||||
|
||||
<script>
|
||||
import { assets } from '$app/paths';
|
||||
import Video from './index.svelte';
|
||||
import DemoContainer from '../_docs/DemoContainer/index.svelte';
|
||||
import {assets} from '$app/paths'; import Video from './index.svelte'; import
|
||||
DemoContainer from '../_docs/DemoContainer/index.svelte';
|
||||
</script>
|
||||
|
||||
<section>
|
||||
|
|
@ -18,14 +17,13 @@ slug: video
|
|||
|
||||
</section>
|
||||
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { assets } from '$app/paths'; // helper if importing video from 'statics'
|
||||
import { Video } from '@reuters-graphics/graphics-svelte-components';
|
||||
</script>
|
||||
|
||||
<Video
|
||||
<Video
|
||||
ariaDescription={"Compulsory description of your video for screen readers."}
|
||||
src={`${assets}/videos/myVideo.mp4`} // or a URL to an external video
|
||||
size={'wide'} // normal, wide, wider, widest or fluid
|
||||
|
|
@ -33,94 +31,94 @@ slug: video
|
|||
/>
|
||||
```
|
||||
|
||||
|
||||
<DemoContainer>
|
||||
<Video
|
||||
<Video
|
||||
ariaDescription="Description of your video for screen readers."
|
||||
src={`${assets}/videos/Sequence silent video_4.mp4`}
|
||||
size='wide'
|
||||
size="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.
|
||||
- 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.
|
||||
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.
|
||||
- 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'}
|
||||
size={'normal'}
|
||||
loopVideo={false}
|
||||
playVideoThreshold={0.9}
|
||||
<Video
|
||||
ariaDescription="{'Compulsory description of your video for screen readers.'}"
|
||||
src="{'path-to-video-or-external-url'}"
|
||||
size="{'normal'}"
|
||||
loopVideo="{false}"
|
||||
playVideoThreshold="{0.9}"
|
||||
/>
|
||||
```
|
||||
|
||||
<DemoContainer>
|
||||
<Video
|
||||
<Video
|
||||
ariaDescription="Description of your video for screen readers."
|
||||
src={`${assets}/videos/Sequence silent video_4.mp4`}
|
||||
size='normal'
|
||||
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"
|
||||
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`
|
||||
- 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`.
|
||||
|
||||
- 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.
|
||||
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
|
||||
<Video
|
||||
ariaDescription={"Compulsory description of your video for screen readers."}
|
||||
src={'path-to-video-or-external-url'}
|
||||
src={'path-to-video-or-external-url'}
|
||||
size={'normal'}
|
||||
caption={'Optional caption for your video.'}
|
||||
playVideoThreshold={0.1}
|
||||
|
|
@ -134,70 +132,69 @@ Here is an example with bottom right corner white opaque controls, with a replay
|
|||
```
|
||||
|
||||
<DemoContainer>
|
||||
<Video
|
||||
<Video
|
||||
ariaDescription="Description of your video for screen readers."
|
||||
src={`${assets}/videos/Sequence silent video_4.mp4`}
|
||||
size='normal'
|
||||
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}
|
||||
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'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.
|
||||
- `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).
|
||||
|
||||
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.
|
||||
- `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.
|
||||
|
||||
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.
|
||||
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'}
|
||||
size={'normal'}
|
||||
controlsOpacity={1}
|
||||
loopVideo={false}
|
||||
muteVideo={false}
|
||||
allowSoundToAutoplay={true}
|
||||
<Video
|
||||
ariaDescription="{'Compulsory description of your video for screen readers.'}"
|
||||
src="{'path-to-video-or-external-url'}"
|
||||
size="{'normal'}"
|
||||
controlsOpacity="{1}"
|
||||
loopVideo="{false}"
|
||||
muteVideo="{false}"
|
||||
allowSoundToAutoplay="{true}"
|
||||
/>
|
||||
```
|
||||
|
||||
<DemoContainer>
|
||||
<Video
|
||||
<Video
|
||||
ariaDescription="Description of your video for screen readers."
|
||||
src={`${assets}/videos/Sequence sound video.mp4`}
|
||||
size='normal'
|
||||
src={`${assets}/videos/Sequence sound video.mp4`}
|
||||
size="normal"
|
||||
caption="World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters"
|
||||
controlsOpacity={1}
|
||||
loopVideo={false}
|
||||
|
|
@ -208,69 +205,65 @@ and go to the top. Click anywhere on the page before scrolling down to the video
|
|||
/>
|
||||
</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.
|
||||
|
||||
- **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'*
|
||||
- **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)
|
||||
- **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*
|
||||
- **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*
|
||||
- **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.
|
||||
- **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)
|
||||
|
||||
- **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.
|
||||
|
||||
- **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_
|
||||
|
||||
- **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.
|
||||
|
||||
- **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.
|
||||
|
||||
- **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.
|
||||
|
||||
- **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.
|
||||
|
||||
- **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.
|
||||
- **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;
|
||||
|
|
@ -290,4 +283,4 @@ Controls the position of the play/pause buttons.
|
|||
margin: 0 5px 0 5px;
|
||||
transform: translateY(-2.5px);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
15
src/components/Video/stories/docs/component.md
Normal file
15
src/components/Video/stories/docs/component.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
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`}
|
||||
size={'wide'}
|
||||
caption={'Optional caption for your video.'}
|
||||
/>
|
||||
```
|
||||
38
src/components/Video/stories/docs/controls.md
Normal file
38
src/components/Video/stories/docs/controls.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
`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.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Video } from '@reuters-graphics/graphics-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}
|
||||
hoverToSeeControls={true}
|
||||
/>
|
||||
```
|
||||
28
src/components/Video/stories/docs/playAndLoop.md
Normal file
28
src/components/Video/stories/docs/playAndLoop.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
`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.
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import { Video } from '@reuters-graphics/graphics-components';
|
||||
</script>
|
||||
|
||||
<Video
|
||||
ariaDescription={"Compulsory description of your video for screen readers."}
|
||||
src={'path-to-video-or-external-url'}
|
||||
size={'normal'}
|
||||
loopVideo={false}
|
||||
playVideoThreshold={0.9}
|
||||
/>
|
||||
```
|
||||
36
src/components/Video/stories/docs/withSound.md
Normal file
36
src/components/Video/stories/docs/withSound.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
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.
|
||||
|
||||
```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'}
|
||||
controlsOpacity={1}
|
||||
loopVideo={false}
|
||||
muteVideo={false}
|
||||
allowSoundToAutoplay={true}
|
||||
/>
|
||||
```
|
||||
|
|
@ -27,5 +27,5 @@ export {
|
|||
themes as SiteHeaderThemes
|
||||
} from './components/SiteHeader/SiteHeader.svelte';
|
||||
export { default as Spinner } from './components/Spinner/Spinner.svelte';
|
||||
// export { default as Video } from './Video/index.svelte';
|
||||
export { default as Video } from './components/Video/Video.svelte';
|
||||
export { default as Visible } from './components/Visible/Visible.svelte';
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@
|
|||
line-height: 1.5rem;
|
||||
color: $tr-dark-grey;
|
||||
margin-bottom: 1rem;
|
||||
// &:last-of-type {
|
||||
// margin-bottom: 0;
|
||||
// }
|
||||
&:last-of-type {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
@media(max-width: 540px) {
|
||||
font-size: 1rem;
|
||||
|
|
@ -45,6 +45,9 @@
|
|||
color: $tr-medium-grey;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.2rem;
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
@media(max-width: 540px) {
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 490 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 315 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 270 KiB |
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue