shadcn.io is not affiliated with official shadcn/ui
Device Management Dialog Block for React
A family notes app's account page with a side sheet of signed-in devices shown open: this device pinned first, Sign out that asks inside the same row, and one button that signs out of all the others the same way.
Installation
Overview
Show people where their account is open and let them close it, with this side sheet for React with Base UI. It opens from the Account page of Hearthnote, a family notes app: the header holds an outline Manage devices Button, and the page itself, a rail of sections and cards with a Devices card that counts and draws one tile for each device, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Sheet lists five devices, this one first with a Badge that says so. Each row has its kind as an icon, its model, its place and the day it was last seen. Sign out turns into "Sign out this device?" with Cancel and Sign out in the same row, so no second dialog opens over the sheet. The foot has one Shine Button, Sign out of all other devices, which asks the same way before it ends the other sessions. Signed-out rows leave the list and the drawn Devices card counts down. For preview the sheet is drawn open in place at the end of the frame when the page loads; the header button opens the real Sheet, with the same list. For account security pages, session lists and anything that can be open on more than one device.
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 frame: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Manage devices 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 DeviceList and DeviceFoot components and share the block's state, so a device signed out in the copy is gone from the real one. 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 from?
From the end of the page's reading direction: the right in a left-to-right page and the left in a right-to-left one. The sheet's own sides are physical, so sideOf reads the page's direction when the sheet opens and passes the matching one. The copy shown on load uses logical positions, so it is already on the right side in either direction. On a phone the copy docks to the foot of the frame as a bottom sheet, and the real sheet is full width.
Why does Sign out ask inside the row?
A dialog over a sheet is two layers of focus trap and two ways to lose your place. Here the row changes in place: its second line asks "Sign out this device?", its button is replaced by Cancel and Sign out, and focus moves to Cancel so a stray Enter backs out. Cancel returns focus to that row's Sign out. Rows keep one height in both states, so nothing below them moves, and on a phone the two buttons are icons that keep their names. This device has no Sign out: ending the session you are using would close the sheet under you.
What does signing out do here, and how do I wire it up?
Here it takes the device out of local state, counts the drawn card down, and says in a polite message that nothing was signed out for real. After a row goes, focus moves to the next row's Sign out, or to the note at the foot of the list when none is left. Sign out of all other devices asks, then keeps only this device. In your app call your server in signOut and signOutAll, revoke the sessions there, keep the row's buttons busy until it answers, and put a failure in the row's second line. Show the last seen time your server records, and sort the newest first.
Where does focus go, and how does it close?
The real sheet is named by its title and described by its sentence, and focus stays inside until it closes. Escape, the close button and a press outside return focus to Manage devices. The trigger is passed to SheetTrigger through render, and the sheet 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.
How do I fill it with my devices?
Edit DEVICES. Each has an id, a kind of laptop, phone or tablet, a name, a place, a current flag for the device in use and a seen day in ISO form, written in UTC so it reads the same on the server and in every visitor's time zone. Keep the current device first. Places are invented here: use the coarse location your server resolves, and say "approximate" if it is a guess from an address.
Related
- Pro
Trusted Devices Account
Sessions and devicesAn account's trusted devices as a table of devices against two switches, one to skip the sign-in code and one to skip the password prompt, with a sentence on what each device's choice means and a meter against the limit.
- Pro
Security Review Account
Sessions and devicesA security review in three sections, devices, recent sign-ins and sign-in methods, where each item is answered with Yes, this is mine or Remove, with a progress bar and a Finish button that waits for every answer.
- Pro
Deactivate 2FA Dialog
Destructive confirmsA security page with its turn-off confirmation shown open: an alert dialog that lists what goes with two-step verification, asks for the password and a ticked acknowledgement, and keeps its destructive action quiet until both are done.
- Pro
A time tracker's Today page with a preferences sheet shown open where each setting shows its effect: a theme choice over a preview card, a text size and a reduce-motion switch acting on a sample, a default view and two behaviour switches.
- Pro
Assign Task Dialog
Side sheetsA sprint board with a side sheet that assigns its one unowned task shown open: five people with their open tasks and load, a priority, a due date from chips or an inline calendar, and a switch to notify the assignee.
- Pro
Filter Sort Dialog
Side sheetsA vinyl shop's records page with its filter panel shown open as a sheet from the start edge: genre chips, a decade list, a two-thumb price range, conditions, an in-stock switch and a sort order, all changing the grid behind it as you touch them.