diff --git a/site/src/components/docs/demos/poster/html/css/BasicUsage.astro b/site/src/components/docs/demos/poster/html/css/BasicUsage.astro
new file mode 100644
index 00000000..e7e95f49
--- /dev/null
+++ b/site/src/components/docs/demos/poster/html/css/BasicUsage.astro
@@ -0,0 +1,10 @@
+---
+import HtmlDemo from '@/components/docs/demos/HtmlDemo.astro';
+import html from './BasicUsage.html?raw';
+import './BasicUsage.css';
+---
+
+
+
diff --git a/site/src/components/docs/demos/poster/html/css/BasicUsage.css b/site/src/components/docs/demos/poster/html/css/BasicUsage.css
new file mode 100644
index 00000000..8facdfae
--- /dev/null
+++ b/site/src/components/docs/demos/poster/html/css/BasicUsage.css
@@ -0,0 +1,52 @@
+.poster-basic {
+ display: block;
+ position: relative;
+}
+
+.poster-basic video {
+ width: 100%;
+}
+
+.poster-basic__poster {
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ transition: opacity 0.25s;
+}
+
+.poster-basic__poster:not([data-visible]) {
+ opacity: 0;
+}
+
+.poster-basic__poster img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.poster-basic__button {
+ position: absolute;
+ bottom: 10px;
+ left: 10px;
+ padding-block: 8px;
+ background: rgba(255, 255, 255, 0.75);
+ backdrop-filter: blur(10px);
+ color: black;
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ border-radius: 9999px;
+ padding-inline: 16px;
+ cursor: pointer;
+}
+
+.poster-basic__button .show-when-paused,
+.poster-basic__button .show-when-playing {
+ display: none;
+}
+
+.poster-basic__button[data-paused] .show-when-paused {
+ display: inline;
+}
+
+.poster-basic__button:not([data-paused]) .show-when-playing {
+ display: inline;
+}
diff --git a/site/src/components/docs/demos/poster/html/css/BasicUsage.html b/site/src/components/docs/demos/poster/html/css/BasicUsage.html
new file mode 100644
index 00000000..da845464
--- /dev/null
+++ b/site/src/components/docs/demos/poster/html/css/BasicUsage.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ Play
+ Pause
+
+
diff --git a/site/src/components/docs/demos/poster/html/css/BasicUsage.ts b/site/src/components/docs/demos/poster/html/css/BasicUsage.ts
new file mode 100644
index 00000000..72060f9f
--- /dev/null
+++ b/site/src/components/docs/demos/poster/html/css/BasicUsage.ts
@@ -0,0 +1,3 @@
+import '@videojs/html/video/player';
+import '@videojs/html/ui/play-button';
+import '@videojs/html/ui/poster';
diff --git a/site/src/components/docs/demos/poster/react/css/BasicUsage.css b/site/src/components/docs/demos/poster/react/css/BasicUsage.css
new file mode 100644
index 00000000..d0d94171
--- /dev/null
+++ b/site/src/components/docs/demos/poster/react/css/BasicUsage.css
@@ -0,0 +1,35 @@
+.poster-basic {
+ position: relative;
+}
+
+.poster-basic video {
+ width: 100%;
+}
+
+.poster-basic__poster {
+ position: absolute;
+ inset: 0;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ pointer-events: none;
+ transition: opacity 0.25s;
+}
+
+.poster-basic__poster:not([data-visible]) {
+ opacity: 0;
+}
+
+.poster-basic__button {
+ position: absolute;
+ bottom: 10px;
+ left: 10px;
+ padding-block: 8px;
+ background: rgba(255, 255, 255, 0.75);
+ backdrop-filter: blur(10px);
+ color: black;
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ border-radius: 9999px;
+ padding-inline: 16px;
+ cursor: pointer;
+}
diff --git a/site/src/components/docs/demos/poster/react/css/BasicUsage.tsx b/site/src/components/docs/demos/poster/react/css/BasicUsage.tsx
new file mode 100644
index 00000000..4d75557a
--- /dev/null
+++ b/site/src/components/docs/demos/poster/react/css/BasicUsage.tsx
@@ -0,0 +1,25 @@
+import { createPlayer, features, PlayButton, Poster, Video } from '@videojs/react';
+
+import './BasicUsage.css';
+
+const Player = createPlayer({ features: [...features.video] });
+
+export default function BasicUsage() {
+ return (
+
+
+
+
+
+
+ }
+ />
+
+
+ );
+}
diff --git a/site/src/content/docs/reference/poster.mdx b/site/src/content/docs/reference/poster.mdx
new file mode 100644
index 00000000..a1408b55
--- /dev/null
+++ b/site/src/content/docs/reference/poster.mdx
@@ -0,0 +1,73 @@
+---
+title: Poster
+frameworkTitle:
+ html: media-poster
+description: Poster image component that stays visible until playback starts
+---
+
+import ApiReference from "@/components/docs/api-reference/ApiReference.astro";
+import FrameworkCase from "@/components/docs/FrameworkCase.astro";
+import StyleCase from "@/components/docs/StyleCase.astro";
+import Demo from "@/components/docs/demos/Demo.astro";
+
+{/* React demos */}
+import BasicUsageDemoReact from "@/components/docs/demos/poster/react/css/BasicUsage";
+import basicUsageReactTsx from "@/components/docs/demos/poster/react/css/BasicUsage.tsx?raw";
+import basicUsageReactCss from "@/components/docs/demos/poster/react/css/BasicUsage.css?raw";
+
+{/* HTML demos */}
+import BasicUsageDemoHtml from "@/components/docs/demos/poster/html/css/BasicUsage.astro";
+import basicUsageHtml from "@/components/docs/demos/poster/html/css/BasicUsage.html?raw";
+import basicUsageHtmlCss from "@/components/docs/demos/poster/html/css/BasicUsage.css?raw";
+import basicUsageHtmlTs from "@/components/docs/demos/poster/html/css/BasicUsage.ts?raw";
+
+## Anatomy
+
+Import the component:
+
+
+ ```tsx
+
+ ```
+
+
+
+ ```html
+
+
+
+ ```
+
+
+## Examples
+
+### Basic Usage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/site/src/docs.config.ts b/site/src/docs.config.ts
index d5982882..19b6f977 100644
--- a/site/src/docs.config.ts
+++ b/site/src/docs.config.ts
@@ -29,6 +29,7 @@ export const sidebar: Sidebar = [
{ slug: 'reference/fullscreen-button' },
{ slug: 'reference/mute-button' },
{ slug: 'reference/play-button' },
+ { slug: 'reference/poster' },
{ slug: 'reference/time' },
],
},