shadcn.io is not affiliated with official shadcn/ui
Hero Section Skeleton Block for Ark UI
A centred home page hero that loads in place: bars become a two-line heading, a sentence, two buttons and a drawn room when you press Load, with the frame real from the start.
Installation
Overview
Show a hero while its content loads, then swap the content in without moving anything, with this hero section skeleton for React with Ark UI. A hairline frame with a plus mark on each corner holds a band heading and the centred hero of Tulle, a lighting-design tool. The frame and the heading are real from the first paint; the two-line heading, the two-line sentence, the two buttons (Start free and See pricing) and the picture are Skeleton bars that become the content in the same boxes, from the top down, when you press Load. Reload goes back to the bars. Once loaded, the buttons are real and say they are not wired in this demo, and a polite line says what loaded. The picture is a drawn greyscale room with a window, a pendant lamp, a sofa and a floor lamp. It's built from Skeleton, Button and Guides, with a CSS entrance only. For marketing pages whose hero comes from a CMS or an experiment.
FAQ
What stays local, and how do I wire it to a real query?
Nothing is fetched. The heading, sentence, button labels and picture are typed in HERO and ROOM, Load starts a 700 millisecond timer, and when it ends the phase becomes ready and the content 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 content when it arrives. The bars sit in the same cells as the content, so keep one component for both.
Why doesn't the hero jump when the content arrives?
Each bar and its content sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. The heading is held to two balanced lines by a width in ch, and the sentence to a set width, so the bars and the text break at the same places. The frame and the labels are real in both phases, and the polite line reserves two lines, so the panel is as tall before, during and after loading. A heading or a paragraph that wraps to more lines than its bars is the one thing that can still move the page, so give a text bar as many lines as the text takes at that width.
Is the picture a photo?
It is drawn: a greyscale scene made of a few SVG shapes whose inks follow the theme, named once by its figure and never a grey box with an icon. In your project, replace the Plate figure with an img that has the same size classes and an alt, and leave the bar as it is; the bar and the image share a box, so the swap still moves nothing.
What do the two buttons do?
Nothing, and they say so: "Start free isn't wired in this demo." They are an outline and a ghost button on purpose, because a hero is not an app's one primary action and the loading state should not shout. They are invisible while the bars show, so they can't be focused before they exist. Point them at your own routes.
Is it accessible?
The region is marked busy while it loads and carries a screen-reader-only "Loading the hero…", and the polite line says 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 content is in, and under reduced motion there is no pulse, no spinner and no stagger: the swap is instant.