Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Playlist Skeleton Block for Ark UI

A playlist that loads in place: a drawn cover, the title, the owner and the track count over seven numbered rows of bars that become titles, artists and lengths when you press Load.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Show a playlist while its tracks load, then swap them in row by row without moving anything, with this playlist skeleton for React with Ark UI. A hairline frame with a plus mark on each corner holds the playlist's header and seven numbered track rows, from Navelwort, a playlist sharing site. The numbers down the side are real from the first paint; the drawn cover, the title, the owner, the "7 tracks, 28 min" line and each track's title, artist and length are Skeleton bars that become the playlist in the same place when you press Load, one row after another. The total time is worked out from the track lengths, so it can't disagree with the list. On a phone the cover shrinks and the rows keep their height. It's built from Skeleton, Guides and Button, with a CSS entrance only. For playlists, queues and any numbered list with two lines to a row.

FAQ

What stays local, and how do I wire it to a real query?

Nothing is fetched. The seven tracks are typed in SONGS, 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 rows when they arrive. The bars are derived from the same data as the content, so keep one component for both.

Where does

From the data: the count is the length of SONGS, and the minutes are the sum of the lengths in seconds, rounded. Change a track and the line follows. In a real app send the total with the playlist, or sum it on the client as here.

Does the panel keep its height while the tracks load?

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. Every row is a fixed height, the cover keeps its square box, and the title and artist share a two-line cell. 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 playlist…", 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 tracks are an ordered list, and the row numbers are decoration because the list already numbers itself.

Where is the play button?

This block is only the loading state of the list, so it has no row controls. Add a play button to each row in a real app, in the same grid column as the length so the row's height doesn't change when it appears.