Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Horizontal Layout Profile Settings Form Block for Radix UI

A settings-page profile form with the label and hint in a 14 rem column at the start and the control at the end, rows on hairlines that stack below 36 rem, an Edited mark on changed rows and a Save button that counts them.

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

Lay a form out like a settings page with this horizontal form for React with Radix UI. A compact header sits over a hairline frame with a plus mark on each corner. Five rows of a coaching platform's profile (Display name and Email as Inputs, Role as a Select, Time format as two radio choices and Bio as a Textarea with a count) each put the label and a hint of one line in a 14 rem column at the start and the control at the end, with a hairline between rows. The panel is a container: below 36 rem each row stacks, label over control, whatever the screen is. A row that differs from what is saved shows an "Edited" badge, a space reserved so nothing moves, and the foot counts them in the button ("Save 2 changes"). Save checks the name and the email, names the first problem in the foot and focuses it; valid changes are kept in the tab and an outline Button discards them. It's built from Input, Select, Textarea, Field, Badge, Button, Shine Button and Guides, with a CSS entrance only. For account and profile settings, admin forms and any page where people scan the labels down one edge.

FAQ

How does the layout switch between horizontal and stacked?

Each row is a grid with @xl:grid-cols-[14rem_minmax(0,1fr)] and the form is an @container, so the switch depends on the width the panel actually has, not on the screen. In a narrow column, or a sidebar, the same form stacks. Change the label column with the 14rem in ROW.

How is a row marked as edited?

edited(key) compares the draft value with the saved one. The "Edited" badge is always rendered and made invisible when the row is unchanged, so the label column never changes height. The count in the first band and in the Save button comes from the same comparison.

When are problems shown?

On Save, for the name (2 letters or more) and the email (an address shape) at once. The first is worded in the status line and its input is focused; each field has a reserved line for its own message, so a problem never moves the rows. Fix the field and the message goes.

Does it work right to left?

Yes. The label column and the control swap sides, the email input stays left to right, and the counts and the hints sit in isolating spans so mixed text reads correctly.

What stays local, and how do I connect it for real?

Nothing is sent: Save says "Saved 2 changes in this demo." To make it real, post the draft from the submit handler, set saved from the answer and show a failure in the status line without losing the draft.

How do I connect it to react-hook-form or TanStack Form?

With react-hook-form, register the five fields; formState.dirtyFields replaces edited and setFocus replaces the focus effect, and the container query keeps working because it only reads the panel's width.