shadcn.io is not affiliated with official shadcn/ui
Podcast Player Skeleton Block for Ark UI
An episode player that loads in place: a drawn artwork, the title, the episode line and a two-line description over a scrubber, skip, play and speed controls, all bars until you press Load.
Installation
Overview
Show an episode player while it loads, then swap the player in without moving anything, with this podcast player skeleton for React with Ark UI. A hairline frame with a plus mark on each corner holds the episode, the progress and the controls of Gneiss, a geology podcast app. The frame is real from the first paint; the drawn artwork, the title, the "Episode 41, 7 Oct" line, the two-line description, both times and every control are Skeleton bars that become the player in the same place when you press Load. Once it is in, the Slider progress moves its own thumb, Play is a pressed Toggle, the speed Native Select keeps its value, and the skips say they are not wired. There is no audio in this demo. It's built from Skeleton, Slider, Toggle, Native Select and Guides, with a CSS entrance only. For podcast apps and any episode that loads before it plays.
FAQ
What stays local, and how do I wire it to a real query?
Nothing is fetched. The episode's details are typed in EPISODE, 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 audio?
No. Nothing plays, and the block says so: the polite line ends with "No audio in this demo." Play is a toggle that only draws its pressed state, so you can see the control work without a sound, and the scrubber moves its own thumb. To make it real, put an audio element behind the toggle, set its currentTime from the scrubber's value and feed the scrubber from its timeupdate event.
Does the panel keep its height while the episode 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 title and the description are each clamped to two lines, the artwork keeps its square box, and every control keeps its size. The frame and the labels are real in both phases and the polite line reserves two lines, so the panel 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 episode…", 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 skip buttons read "Back 15 s" and "Forward 30 s", the speed select is named "Playback speed", and the progress reads its value as time.