Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Passkeys Account Block for Radix UI

An account's passkeys: a ruled list of what each one is, when it was created and last used, a name you edit in place, a guarded Remove, and a dialog from the header that names a new passkey.

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

Let people manage how they sign in without a password, with this passkey list for React with Radix UI. A compact header holds the title and the one Shine Button, Add a passkey, which opens a real Dialog. Inside a hairline frame with a plus mark on each corner, a ruled list shows every passkey: an icon for a device or a security key, its name, where it was made, and from the medium breakpoint its created and last-used dates in their own columns. Each name is an Editable you rename in place; Remove opens an Alert Dialog that says when it is the last passkey and a password would be the only way in. Remove them all and an Empty state offers to add one. A native disclosure at the foot answers what a passkey is in three lines. It's built from Dialog, Alert Dialog, Editable, Field, Input, Empty, Badge, Button, Shine Button and Guides, with a CSS entrance only. For the security page of any app, banking or otherwise.

FAQ

How do I fill it with my own passkeys?

Edit PASSKEYS at the top. Each has an id, a name the person chose, a kind (laptop, phone or key, which picks the icon and the word Device passkey or Security key), the browser and system it was made on as where, the ISO days it was created and last used (empty when it never has) and here, true for the one on the device in use, which gets a This device badge. Dates are formatted in UTC so they read the same on the server and in every time zone. Counts and the empty state are worked out from the list.

What does Add a passkey do, and what stays local?

It asks for a name (an empty or repeated one is refused under the field, which keeps focus), then adds a row at the end and moves focus to it. No WebAuthn call is made and nothing is registered with a browser or a server: the dialog says so, and so does the status line. To make it real, call navigator.credentials.create() with options from your server in the submit handler, send the result back to be stored, and add the row from the response.

How does renaming work?

Click a name or press the pencil next to it to edit in place. Enter or leaving the field saves, Escape or the cross puts the old name back. An empty name or one that another passkey already has keeps the old name and says why in the status line. The name is only a label for the person, so renaming needs no confirmation; send it to your server in commit.

Why does Remove ask, and what does it say for the last passkey?

Removing a passkey can lock someone out if it is their way in, so it opens an alert dialog (no outside click closes it, Escape and Keep it do). When it is the only passkey the first sentence says a password is then the only way into the account. Confirming removes the row in the page and moves focus to the next row, or to the Add button in the empty state. Each row's dialog is controlled with open and onOpenChange, and its trigger is the button wrapped in AlertDialogTrigger with asChild.

Is it accessible?

The list is a real list named Passkeys, and each row's dates are a description list whose terms are hidden from view once the columns have their own heads, so a screen reader hears Created and Last used either way. Every button names its passkey ("Remove Work laptop", "Rename Desk key"). The dialogs trap focus, close with Escape and return focus; the new row, or the row after a removal, takes focus. One polite status line reports each add, rename and removal.

How does it look on a phone?

Each row keeps its icon and name and stacks the two dates and Remove under them; the column heads are gone because the dates carry their own labels. The header button drops under the sentence. The dialogs are the catalog's: a sheet stuck to the bottom of the screen.