shadcn.io is not affiliated with official shadcn/ui
Drawer Wizard Stepper Block for React
A sensors dashboard with a side sheet shown open that adds a sensor in four steps: a hub to pair, a new name, a lower and upper alert limit checked together, and a read-back, ending on a new tile behind it.
Installation
Overview
Take a setup flow into a side sheet, with this stepper for React with Base UI. It opens from the Sensors page of Sentrio, a home monitoring console: the header holds an outline Add sensor Button and the page, a grid of tiles with a name, a last reading and an alert range, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Sheet opens at the end of the page and holds a strip of four short segments, one per step (Hub, Name, Limits, Review), that fills as you go; the segments you have reached are buttons, so Back is free. A Radio Group picks the hub, a name Input refuses an empty name or one already in use, two number fields set the lower and upper alert limits and must make sense together, and a Data List reads it all back. The foot has Back and the block's one Shine Button, which reads Continue, then Add sensor, then Done; adding puts a new tile on the dashboard behind the sheet. For preview the sheet is drawn open in place when the page loads; the header button opens the real sheet with the same step and the same answers. For device setup, monitoring and any flow that belongs beside the page it changes.
FAQ
Why is the sheet already open, and what do I keep?
So you can see it without a click. On load the sheet is a copy drawn in place at the end of the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused. The header button opens the real Sheet, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same SensorWizard component and share the block's state, so a sensor begun in the copy carries on in the real sheet at the same step. In your app keep the Sheet and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
Which side does the sheet open on, and why?
The end of the page: the right in a left-to-right layout and the left in a right-to-left one. The Sheet's sides are physical, so the block reads the page's direction when the sheet opens and passes left or right to match; the copy shown on load uses logical positions and follows the direction by itself. On a phone the real sheet is full width.
How are the limits checked?
On Continue, together: both must be numbers, both between -20 and 60 degrees, and the upper one above the lower. The message sits under the two fields in a slot two lines high, so the sheet never grows, and focus returns to the lower limit when Continue is refused. A comma works as a decimal point. The limits are plain text fields with a decimal keyboard on phones, so each keystroke is read the same way on every base.
What stays local, and how do I make it real?
Everything. The new sensor lives in component state, and Add sensor puts a tile with "No reading" on the drawn dashboard and says "Added in this demo": nothing is paired and nothing is installed. In your app send hub, name, low and high to your server from add, and add the tile from its response; a server that refuses the name should return its reason for the name field.
Is it accessible from the keyboard?
Yes. The strip is one tab stop on the current step: arrow keys move between the segments you can reach, and Enter or Space opens one; each segment is named by its step. Enter in a field presses Continue. The real sheet is named by its title and described by its sentence, and Escape, the close button and Done all return focus to Add sensor. The trigger is passed to SheetTrigger through render, and the sheet is controlled with open and onOpenChange.