Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Basic Form Skeleton Block for Ark UI

A maintenance request editor that loads in place: real labels and helper lines over four fields of bars that become a subject, a unit, a priority and the details 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 form while its record loads, then swap the values in without moving anything, with this basic form skeleton for React with Ark UI. A hairline frame with a plus mark on each corner holds a band heading and four stacked fields from Hyssop, a property manager's request tracker. The labels (Subject, Unit, Priority, Details) and their helper lines are real from the first paint; each value is a Skeleton bar that becomes an Input, a Native Select or a Textarea in the same box, top to bottom, when you press Load. Reload goes back to the bars. The frame's bands are ruled by Guides, the load control is an outline Button, the one primary is a Shine button that stays unavailable while the request loads, and a polite line says what loaded and what Save did. On a phone the foot stacks. For edit pages, detail drawers and any form that waits for a query.

FAQ

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

Nothing is fetched or saved. The request is typed in REQUEST, 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 form when the data arrives. Save is a local line: replace the submit handler with your mutation.

Why doesn't the form jump when the values arrive?

Each bar and its control sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. The labels, the helper lines, the heading and the buttons are real in both phases, every bar has the height of the control it stands in for, and the polite line reserves two lines, so the panel is exactly as tall before, during and after loading at every width.

How do I use the Cell helper in my own form?

Cell takes a bar class for the placeholder's size and the real control as its children. Give the bar the control's height (h-8 for an input) and w-full, and it renders the bar and the control in one grid cell. Set at to the field's index and the reveal staggers by 70 milliseconds a step. Pass fit so the control's focus ring isn't clipped.

Is it accessible?

The region is marked busy while it loads and carries a screen-reader-only "Loading request…", 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 a field is neither read nor focusable until its data is in. Every control has a real label, and Save is aria-disabled rather than removed while it waits. 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.

What does Save do?

Nothing is saved, and the polite line says so: "Saved in this demo. Nothing was sent." While the request loads Save is aria-disabled and ignores a press, so a half-loaded form can't be submitted. Wire the form's onSubmit to your mutation and show its error with a Field error.