Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

No Contacts Empty State Block for Radix UI

A contacts book's empty state with two tabs: Add one, a name, email and company form, and Import CSV, a drop zone that reads the file's header in your browser; one button for the active tab and an address-card tray whose dashed place turns solid.

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

Give the first contact two ways in, with this no contacts empty state for React with Radix UI. A hairline frame with a plus mark on each corner holds the contacts book of Tansybook, with Tabs over its form. Add one asks for a name and an email, and a company if you like, in Fields with their problems said in a line that holds its space. Import CSV is a File Upload drop zone with the first line it expects shown as chips (name, email, company); it reads your file in the tab, checks the header and counts the rows it can use, without uploading anything. One Shine Button, the only colored control, is the active tab's action: "Add contact", or "Import 3 contacts" once a file is ready. At the end an address-card tray holds three cards behind a dashed place for the next one, which turns solid and carries the newest contact's initials, over a list of three places that fill as contacts arrive. The frame is ruled by Guides, the tray is one SVG whose classes change, and the transitions are CSS only. For the first-run state of any contact or address book.

FAQ

What stays in the page, and how do I make it real?

The contacts live in the page's state: reload and the book is empty, and Start over empties it without a reload. A chosen file is read in the browser and never uploaded, and nothing is saved or sent. To wire it for real, post the contact, or the rows of the file, to your API where the code says so, and add the saved records from the response.

How is the CSV read?

The first line names the columns: it needs name and email, and may have company, in any order and any case. Each line after it is one contact. A comma inside double quotes stays in its cell. Rows without a name, with an email that is not an address, or whose email is already in the book or earlier in the file are left out, and the line under the zone says how many are ready and how many were skipped. Files that are not .csv are refused with a line that says so.

Why only three contacts?

It is the demo's limit, so the list can keep its size and both tabs their height. With three in the book the button stays in the tab order and says the demo is full, and a file with more rows imports as many as fit. Take the limit out and let the list scroll in your app.

Do the tabs keep what I typed?

Yes. The fields, the chosen file and the list are the block's state, not the tab's, so switching tabs and back leaves them as they were. Both tabs are the same height, so the button and the list under it never move when you switch.

Is it usable with a keyboard and a screen reader?

The tabs are a real tab list, the fields have labels, the drop zone is a focusable button named for what it takes, and pressing Enter in a field submits the form. One polite status line says each result, and the tray drawing is decoration, hidden from assistive technology, with the same facts in the list beside it.

How does it look on a phone?

The three fields stack and the active tab's button stays pinned to the foot of the screen while the panel is in view. The tray and the list come after it. Nothing scrolls sideways at 320 px.