shadcn.io is not affiliated with official shadcn/ui
Compact Card Skeleton Block for Radix UI
A pinned-pages rail that loads in place: four compact cards on hairlines whose icon tiles, titles, one-line descriptions and Open buttons come in over bars, one after another, when you press Load.
Installation
Overview
Show a rail of small cards while it loads, then swap the content in without moving anything, with this compact card skeleton for React with Radix UI. A hairline frame with a plus mark on each corner holds a band heading and four compact cards on shared hairlines: the pinned pages of Percale, a team wiki. The heading is real from the first paint; each card's icon tile, title, one-line description and Open button, and the count in the heading, are Skeleton bars that become the page in the same place, card by card from the top. Every card is a fixed height with a description that truncates to one line, the bands are ruled by Guides, and each Open is a ghost Button named for its page that says it is not wired in this demo. It's built from Skeleton, Button and Guides, with a CSS entrance only. For pinned items, shortcuts and any short rail of small cards.
FAQ
What stays local, and how do I wire it to a real query?
Nothing is fetched. The four pages are typed in PINS, each with its own icon. 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 card from your query's pending state, or use the bars as a Suspense fallback and render the real content when it arrives. Keep one component for the bars and the data so they can't drift apart.
Why doesn't the card jump when the data arrives?
Each card is a fixed h-16 row, and every bar shares a grid cell with the text it becomes, so the larger of the two sets the box. The description truncates to one line, so a longer title or line can't grow a row. The heading is real in both phases and the polite line reserves two lines, so the rail is exactly as tall before, during and after loading.
How do I change the icons or add a card?
Each pin carries its icon as a field (icon: LucideIcon), drawn in a neutral tile. Add an object to PINS with an icon, an id, a title and a line, and the rail, the count in the heading and the polite line follow. Keep the row height fixed; a fifth card makes the rail taller in every phase alike. Swap the icon set by changing the import, since the tile only needs a component with a className.
What does Open do, and how do I wire it?
Nothing here: it sets the polite line to "Open Onboarding checklist isn't wired in this demo." The button's accessible name includes the page's title, and it is a bar of its size until the card arrives, so it can't be focused early. In your app, make Open a link to the page, or make the whole card the link and drop the button.
Is it accessible?
The card is marked busy while it loads and carries a screen-reader-only "Loading pinned pages…", 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.