Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Onboarding Welcome Dialog Block for Ark UI

A project planner's empty workspace with a four-step welcome dialog shown open that you can leave and resume: named dots as a tablist, a progress line, Back and Next, and a header button that reads Resume welcome, step 2 of 4.

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

Greet a new workspace without trapping anyone in a tour, with this welcome dialog for React with Ark UI. It opens from Your workspace in Slatewright, a project planner: the page's header holds an outline Start welcome Button, and the app, a sidebar with a Help item beside an empty state that says no projects yet, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog has four steps, Welcome, Your boards, Shortcuts and Invite, each a small drawn tile, a title and two lines. Named dots, a Tabs list, count them: each is a tab named like Step 2 of 4: Your boards, with a hairline Progress line under them, Back, a ghost Skip for now and the only Shine Button, Next, which reads Open my workspace on the last step. Closing at any point keeps your place, so the header button reads Resume welcome (step 2 of 4); finishing turns it into Welcome complete and the drawn empty state into Workspace ready. For preview the dialog is drawn open in place when the page loads; the header button opens the real Dialog.

FAQ

Why is the dialog already open, and what do I keep?

So you can see it without a click. On load the dialog is a copy drawn in place over the app: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Start welcome button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same WelcomeFields component and share the block's state, so the step you reached in the copy is the step the real one opens on. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.

How does it remember where I was?

The step is part of the block's state and closing the dialog does not reset it. Close it on step 2 with the close button, Escape or Skip for now, and the header button reads Resume welcome (step 2 of 4); open it and you are on step 2. Finishing sets a done flag: the button reads Welcome complete, and opening it again starts over from step 1. In your app save the step with the user's profile so the welcome resumes on another device too.

What does Skip for now do?

It asks nothing. It closes the dialog, keeps your place and says where the welcome lives: "You can open this again from Help." The drawn workspace behind it repeats that under its empty state and rings its Help item. Nothing is stored in the demo; your app would remember the skip so it does not open the welcome by itself again.

How do the dots work?

They are a tab list: the arrow keys move between them and choose a step, Tab moves on to the panel and the buttons, and each dot is named by its step, such as Step 3 of 4: Shortcuts, with the count and the title also written beside them. The finished steps are drawn half solid and the current one solid. All four panels sit in one place, three of them unseen, so the dialog keeps its height whichever step shows.

What stays local in the demo, and how do I wire it up?

All of it. The steps, their words and the drawn tiles are typed here, and the place, the finished flag and the skip live in the block's state. In your app load the steps from your content, save progress on each step, and mark the welcome done on the last one.

Is it accessible from the keyboard?

Yes. The real dialog is named Welcome to Slatewright, focus starts inside and stays there until it closes, and Escape and the close button return focus to the header button. Next, Back and Skip for now are ordinary buttons, Back is quiet on the first step and says so when pressed, and a polite message announces each step. The trigger is the button wrapped in DialogTrigger with asChild, and the dialog is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it and its close button close it and put focus on the button.