Video Player

@sushindustries/ui

A video held behind a picture of itself. The player is a child, so it mounts on play and unmounts on stop.

Last updated Aug 17, 20269 min read
View as MarkdownEdit on GitHub

Examples are the tab where the component is shown doing a job, not demonstrating a prop. The API tab already lists the props.

Viewport width
Phone22remthe floor, the narrowest this promises to work at
tanstacktanstack add https://adamjurek.com/r/tanstack/video-player.jsonshadcnpnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/video-player.json

Press Compare. The frames are real viewports, so a layout that breaks at 320 breaks here too rather than in somebody's hands.

In a page

This site's Markdown video block is what active and onActiveChange exist for: a TanStack Store holds the id of whichever block is playing, so starting a second video stops the first without either block knowing the other exists.

import { VideoPlayer } from "@sushindustries/ui";
import { useStore } from "@tanstack/react-store";
import { useId } from "react";
import { playingVideo, playVideo, stopVideo } from "./video.store";

export function VideoBlock({ id, title, poster, embedUrl }: BlockProps) {
	const blockId = useId();
	const playing = useStore(playingVideo);
	const active = playing === blockId;

	return (
		<VideoPlayer
			title={title}
			provider="youtube"
			poster={poster}
			active={active}
			onActiveChange={(next) => (next ? playVideo(blockId) : stopVideo(blockId))}
		>
			<iframe src={embedUrl} title={title} allowFullScreen />
		</VideoPlayer>
	);
}
tsx

playVideo and stopVideo write one id into the store; every block on the page reads it and compares it to its own useId(), so the component itself never needs to know how many siblings it has.

What this example is not

The store (playingVideo, playVideo, stopVideo) is the site's own code, not something VideoPlayer ships. Without it - passing no active at all - the component is fully usable, just uncontrolled: each instance owns its own open/closed state and two on one page can play at once.

UsesIconIconThe glyph set, generated from a Markdown table where every drawing carries its reason. One component, typed names, no icon font.@sushindustries/ui · content