shadcn.io is not affiliated with official shadcn/ui
Media Player Skeleton Block for React
A video player window that loads in place: a drawn 16:9 stage, a scrubber, play, skip, volume and full screen controls and the talk's details, all bars until you press Load.
Installation
Overview
Show a video player while its talk loads, with this media player skeleton for React with Base UI. One framed window from Scupper, a talks archive, has a top bar with the "Now playing" heading and the Load control, a page that scrolls inside it, and a one-line status foot. The window is real from the first paint; the drawn 16:9 stage, the scrubber, every control and the talk's title, speaker and views are Skeleton bars that become the player in the same place when you press Load. Once it is in, the Slider scrubber and the volume move their own thumbs and the time beside them follows the scrubber, Play is a pressed Toggle, and the skips and full screen say they are not wired. The stage says "No video in this demo". It's built from Skeleton, Slider, Toggle, Button and Guides, with a CSS entrance only. For talk archives, course lessons and any page that loads a video.
FAQ
What stays local, and how do I wire it to a real query?
Nothing is fetched. The talk's details are typed in TALK, Load starts a 700 millisecond timer, and when it ends the phase becomes ready and the data swaps in; Reload goes back to the bars and in again. To wire it for real, delete the timer, the Load button and the polite line, and set data-state (loading or ready) and aria-busy on the region from your query's pending state, or use the bars as a Suspense fallback and render the real player when they arrive. The bars are derived from the same data as the content, so keep one component for both.
Does it play video?
No, and it says so on the stage and in the status foot. Play is a toggle that only draws its pressed state. To make it real, put a video element in the stage, call its play and pause from the toggle, set currentTime from the scrubber and feed the scrubber from the element's timeupdate event.
Does the window keep its size while the talk loads?
Each bar and its data sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. The stage keeps its 16:9 box, each control keeps its size, and the window itself has a fixed height, so only the page inside it scrolls. The frame and the labels are real in both phases and the polite line reserves two lines, so the window is exactly as tall before, during and after loading at every width.
Is it accessible?
The region is marked busy while it loads and carries a screen-reader-only "Loading talk…", and the polite line announces what loaded once. The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. The pulse stops when the data is in, and under reduced motion there is no pulse, no spinner and no stagger: the swap is instant. The scrubber and the volume are named, announce their value as text ("1:12 of 31:05", "60% volume") and move with the arrow keys, and every icon button has a name.