-
-
-
diff --git a/src/components/TestForSvelte5/stories/docs/component.md b/src/components/TestForSvelte5/stories/docs/component.md
deleted file mode 100644
index 552459cb..00000000
--- a/src/components/TestForSvelte5/stories/docs/component.md
+++ /dev/null
@@ -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
-
-
-
-
-```
diff --git a/src/components/TestForSvelte5/stories/shark.jpg b/src/components/TestForSvelte5/stories/shark.jpg
deleted file mode 100644
index 352b0ab9..00000000
Binary files a/src/components/TestForSvelte5/stories/shark.jpg and /dev/null differ
diff --git a/src/components/Video/Controls.svelte b/src/components/Video/Controls.svelte
deleted file mode 100644
index 401d1408..00000000
--- a/src/components/Video/Controls.svelte
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
diff --git a/src/components/Video/Video.mdx b/src/components/Video/Video.mdx
new file mode 100644
index 00000000..737de61f
--- /dev/null
+++ b/src/components/Video/Video.mdx
@@ -0,0 +1,155 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as VideoStories from './Video.stories.svelte';
+
+
+
+# Video
+
+The `Video` component adds a video with various controls to your page such as:
+
+- Play/pause button
+- Autoplay controls, i.e. whether the video plays when it comes into view or on page load
+- Looping
+- Audio controls
+- Text elements such as notes and titles
+
+```svelte
+
+
+
+```
+
+
+
+## Using with ArchieML docs
+
+With the Graphics Kit, you'll likely get your text value from an ArchieML doc...
+
+```yaml
+# ArchieML doc
+[blocks]
+type: video
+src: videos/my-video.mp4
+width: wide
+ariaDescription: Required description of your video for screen readers.
+notes: Optional caption for your video.
+loopVideo: true
+[]
+```
+
+... which you'll parse out of a ArchieML block object before passing to the `Video` component.
+
+```svelte
+
+
+
+{#each content.blocks as block}
+ {#if block.type === 'video'}
+
+ {/if}
+{/each}
+```
+
+> **Note:** Some props, like `loopVideo`, expect boolean values. If you're using the Graphics Kit, you can use the `truthy()` util function to convert a string value to a boolean.
+
+## Autoplay controls
+
+By default, the video starts playing when 50% (0.5) of the video element's height comes into view. Adjust this with `playVideoThreshold`, which is a value between 0 and 1, where 0 means the video will start playing as soon as its top enters the viewport, and 1 means it will start when the whole video is in the viewport.
+
+To make the video play on page load regardless of whether it is in view, set the prop `playVideoWhenInView` to `false`.
+
+```svelte
+
+
+
+```
+
+
+
+## Audio controls
+
+On most browsers, [autoplaying videos with sound](https://developer.chrome.com/blog/autoplay#:~:text=Muted%20autoplay%20is%20always%20allowed,to%20allow%20autoplay%20with%20sound.) is allowed only if the user has interacted with the page. (Autoplay is allowed with muted videos.)
+
+By default, this component will not autoplay videos with sound. To change this, set `soundAutoplay` to `true`. This will allow the video to autoplay with sound when it comes into view, but only if the user has already interacted with the page by clicking or tapping on it.
+
+Test this with the example below: the video will autoplay when it comes into view _only if_ you have clicked or tapped on the page before scrolling down to it.
+
+```svelte
+
+
+
+```
+
+
+
+## Adding text
+
+The `Video` component allows you to add a title, description and notes to your video, which are rendered by the `GraphicBlock` component.
+
+Customise the `notes` section by passing a [snippet](https://svelte.dev/docs/svelte/snippet) instead of a string.
+
+```svelte
+
+
+
+
+
+```
+
+
diff --git a/src/components/Video/Video.stories.svelte b/src/components/Video/Video.stories.svelte
index 71a87ef5..90705f44 100644
--- a/src/components/Video/Video.stories.svelte
+++ b/src/components/Video/Video.stories.svelte
@@ -1,46 +1,22 @@
-
- {#snippet children({ args })}
-
- {/snippet}
-
-
+
+
-
+
+
+
+
+
diff --git a/src/components/Video/Video.svelte b/src/components/Video/Video.svelte
index 24bbbd1a..d05c784d 100644
--- a/src/components/Video/Video.svelte
+++ b/src/components/Video/Video.svelte
@@ -1,169 +1,200 @@
-
+
+{#snippet controls()}
+
+{/snippet}
+
+
+{#snippet transparentButton()}
+
+{/snippet}
+
- {#if $$slots.notes}
-
-
+
+ {#if notes && typeof notes !== 'string'}
+ {@render notes()}
{/if}
+
+
diff --git a/src/components/Video/stories/videos/silent-video.mp4 b/src/components/Video/demo/silent-video.mp4
similarity index 100%
rename from src/components/Video/stories/videos/silent-video.mp4
rename to src/components/Video/demo/silent-video.mp4
diff --git a/src/components/Video/stories/videos/sound-video.mp4 b/src/components/Video/demo/sound-video.mp4
similarity index 100%
rename from src/components/Video/stories/videos/sound-video.mp4
rename to src/components/Video/demo/sound-video.mp4
diff --git a/src/components/Video/docs.svx b/src/components/Video/docs.svx
deleted file mode 100644
index ee3fb08e..00000000
--- a/src/components/Video/docs.svx
+++ /dev/null
@@ -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
----
-
-
-
-
-
- ## {title}
-
- {description}
-
-
-
-```svelte
-
-
-
-```
-
-
-
-
-
-
-
-#### 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.
-
-
-
-```svelte
-
-
-
-```
-
-
-
-
-
-
-
-#### 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.
-
-
-
-```svelte
-
-
-
-```
-
-
-
-
-
-
-
-#### 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.
-
-
-
-```svelte
-
-
-
-```
-
-
-
-
-
-
-
-### 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 **" " (none)** options: Write a caption to go with the video.
-
-- **size** (string) - default **'normal'** options: _'normal'_, _'wide'_, _'wider'_, _'widest'_, _'fluid'_
-
-- **preloadVideo** (string) - default **'auto'**
- options: _'none'_ (Don't preload the video on page load),
- _'auto'_ (Preload the video),
- _'metadata'_ (Only preload the metadata)
-
-- **loopVideo** (bool) - default **true** options: _true_, _false_
-
-- **muteVideo** (bool) - default **true** options: _true_, _false_
-
-- **allowSoundToAutoplay** (bool) - default **false** 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 **true**
- 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 **0.5** 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 **true** options: _true_, _false_
-
-- **showControls** (bool) - default **true** options: _true_, _false_.
- Whether to show the play/pause controls or not.
-
-- **hoverToSeeControls** (bool) - default **false** options: _true_, _false_.
- Whether you need to hover over the video to see the controls.
-
-- **separateReplayIcon** (bool) - default **false** options: _true_, _false_.
- Whether to use a separate replay icon or use the play icon for replay as well.
-
-- **controlsColour** (colour string) - default **'#333'** options: _any valid colour string_.
- Controls the colour of the play/pause buttons.
-
-- **controlsOpacity** (float) - default **0.5** options: _float between 0 and 1_.
- Controls the opacity of the play/pause buttons.
-
-- **controlsPosition** (string) - default **'top left'**
- options: _'top right'_, _'top left'_, _'bottom right'_, _'bottom left'_.
- Controls the position of the play/pause buttons.
-
-
-
-
diff --git a/src/components/Video/stories/docs/component.md b/src/components/Video/stories/docs/component.md
deleted file mode 100644
index 207bd677..00000000
--- a/src/components/Video/stories/docs/component.md
+++ /dev/null
@@ -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
-
-
-
-```
diff --git a/src/components/Video/stories/docs/controls.md b/src/components/Video/stories/docs/controls.md
deleted file mode 100644
index 87e8f916..00000000
--- a/src/components/Video/stories/docs/controls.md
+++ /dev/null
@@ -1,38 +0,0 @@
-`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`, `center` 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
-
-
-
-```
diff --git a/src/components/Video/stories/docs/playAndLoop.md b/src/components/Video/stories/docs/playAndLoop.md
deleted file mode 100644
index 03427fd0..00000000
--- a/src/components/Video/stories/docs/playAndLoop.md
+++ /dev/null
@@ -1,28 +0,0 @@
-`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
-
-
-
-```
diff --git a/src/components/Video/stories/docs/withSound.md b/src/components/Video/stories/docs/withSound.md
deleted file mode 100644
index 50620899..00000000
--- a/src/components/Video/stories/docs/withSound.md
+++ /dev/null
@@ -1,36 +0,0 @@
-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
-
-
-
-```
diff --git a/src/components/Video/types.ts b/src/components/Video/types.ts
new file mode 100644
index 00000000..56989e6a
--- /dev/null
+++ b/src/components/Video/types.ts
@@ -0,0 +1,6 @@
+export type ControlsPosition =
+ | 'middle'
+ | 'top right'
+ | 'top left'
+ | 'bottom right'
+ | 'bottom left';
diff --git a/src/components/Video/utils.ts b/src/components/Video/utils.ts
new file mode 100644
index 00000000..b08a877f
--- /dev/null
+++ b/src/components/Video/utils.ts
@@ -0,0 +1,19 @@
+import type { ControlsPosition } from './types';
+
+/** Returns the CSS positions for the controls button */
+export const getButtonPosition = (
+ controlsPosition: ControlsPosition,
+ borderOffset: number
+) => {
+ if (controlsPosition === 'top left')
+ return `top: ${borderOffset}px; left: ${borderOffset}px;`;
+ if (controlsPosition === 'top right')
+ return `top: ${borderOffset}px; right: ${borderOffset}px;`;
+ if (controlsPosition === 'bottom left')
+ return `bottom: ${borderOffset}px; left: ${borderOffset}px;`;
+ if (controlsPosition === 'bottom right')
+ return `bottom: ${borderOffset}px; right: ${borderOffset}px;`;
+
+ // Otherwise, centre it
+ return `top: 50%; left: 50%; transform: translate(-50%, -50%);`;
+};