--- status: draft date: 2025-02-05 --- # Poster Display component for video poster image. Shows before playback starts, hides after. ## Problem Video players show a poster image before playback. The poster: 1. Gives users a preview of the content 2. Should hide once playback starts 3. May optionally reappear when playback ends Existing solutions (Media Chrome, Vidstack) either: - Manage the image internally via `src` prop - Expose complex state (`data-loading`, `data-error`, `data-hidden`, `data-visible`) We want a simpler approach: expose minimal state, let the user control the image. ## Solution Minimal components that: 1. Expose `data-visible` for CSS-based show/hide 2. Do nothing else **HTML:** Wrapper element that accepts `` as child. **React:** Renders `` directly — no wrapper needed. ### Usage #### HTML ```html Video description ``` #### React ```tsx import { Poster } from '@videojs/react'; ; ``` #### CSS ```css media-poster:not([data-visible]) { display: none; } ``` ### With Responsive Image #### HTML ```html Video description ``` #### React ```tsx ``` User controls the image entirely — responsive images, lazy loading, placeholder strategies all work naturally. ### With Placeholder (Blurhash / LQIP) Use CSS `background-image` on the `` element to show a placeholder while the main image loads. When the `src` loads, it naturally covers the background. #### HTML ```html Video description ``` #### React ```tsx ``` For fade transitions (blur → sharp), handle the `load` event on the image: ```html Video description ``` ## API ### Data Attributes | Attribute | Description | | -------------- | -------------------------------------------- | | `data-visible` | Present when poster should show (`!started`) | ### Visibility Logic ```ts visible = !playback.started; ``` The poster is visible until playback has started. Once `started` becomes `true` (user plays or seeks), the poster hides and stays hidden. **Note:** `started` persists — pausing doesn't reset it. The poster only shows on initial load or after a new source is loaded. ## Styling Notes The component sets no default styles. Recommended CSS: ```css media-poster { position: absolute; inset: 0; pointer-events: none; } media-poster:not([data-visible]) { display: none; } media-poster img { width: 100%; height: 100%; object-fit: contain; } ``` **`pointer-events: none`** — Clicks should pass through to the video or play button beneath. ## Accessibility **Wrapper (``):** No ARIA role needed. Custom elements have no implicit role, so there's no semantics to hide or override. Do not add `aria-hidden` to the wrapper — the poster image may be informative. **Child (``):** User provides appropriate `alt` text describing the poster content (e.g., `alt="Keynote speaker at a conference"`). If purely decorative, use `alt=""`. Whether a poster is informative or decorative is the author's judgment (per [WAI guidelines](https://www.w3.org/WAI/tutorials/images/decorative/)). In most video player contexts, posters are informative — they give users a preview of the video content. This is an advantage over Media Chrome (which forces `aria-hidden="true"` on the internal image) and native `