shadcn.io is not affiliated with official shadcn/ui
Connect Account Sheet Block for Ark UI
A link-in-bio builder's settings page with a side sheet of five linked services shown open: connected, not connected and expired rows, Connect and Reconnect that flip locally, and Disconnect that asks in the row first.
Installation
Overview
Show which services an account can read from and let people change that, with this side sheet for React with Ark UI. It opens from the Settings page of Linkloft, a link-in-bio builder: the header holds an outline Manage connections Button, and the page, a rail of sections beside rows of settings and an Integrations row that counts the connected services with a disc for each, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Sheet lists five services named in text with a two-letter tile: Google, GitHub, Slack, Notion and Linear. A row is Connected as an address with Disconnect, Not connected with Connect, or Expired, marked with a Badge, with Reconnect. Connect and Reconnect flip the row and say that no sign-in window opened. Disconnect turns the row's second line into "Auto-import stops. Disconnect?" with Cancel and Disconnect in the same row. The foot repeats that connecting is simulated, above Done, the only Shine Button. 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.
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 connections 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 AccountList and AccountFoot components and share the block's state, so a service connected in the copy is connected in 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. 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 Disconnect ask inside the row?
A dialog over a sheet is two focus traps and two ways to lose your place. Here the row changes in place, its buttons become Cancel and Disconnect, and focus moves to Cancel so a stray Enter backs out. Cancel returns focus to that row's Disconnect. Rows keep one height in both states, so nothing moves, and on a phone the buttons are icons that keep their names. Connect and Reconnect need no question: they only add access, and Disconnect is one press away.
What stays local in the demo, and how do I wire it up?
All of it. Connecting changes the row in this page's state and says "No sign-in window opened and nothing was linked"; no OAuth window opens and no token exists. In your app start the provider's authorisation from connect (a redirect or a popup), mark the row connected only when your server confirms the token, show the account it connected as, and revoke the token on the provider's side in disconnect. An expired row is one whose token your server could not refresh.
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, Done and a press outside return focus to Manage connections. After a row changes, focus lands on the control that replaced the one you pressed. The trigger is the Manage connections button wrapped in SheetTrigger with asChild, and the sheet is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it, Done and its close button close it and put focus on the button.
How do I list my own services?
Edit ACCOUNTS. Each has an id, a name, a two-letter mark that is typed, not derived, so Slack and Sketch stay apart, and a link of connected, expired or none. The tile stands where a logo you have the rights to use would go; never redraw a brand's mark. Services are named in text only.