OAuth connectPro
The card an assistant shows when a tool needs an account: who runs the server, what it may do in one plain sentence, and one button to connect.
On this page
Installation
Usage
import { OAuthConnect } from "@/components/ui/chatcn/pro/oauth-connect"
<OAuthConnect
service={{ name: "Ledgerline", host: "mcp.ledgerline.app", publisher: "Ledgerline AS", verified: true }}
reason="Needed to read the invoices that are past their due date."
scopes={scopes}
status={status}
onConnect={(scopes) => startOAuth(scopes)}
onCancel={cancelOAuth}
/>The header names the server host in mono and says who publishes it. A server the host has verified gets a green shield and the publisher; anything else says Unverified publisher in amber, so people know who they are trusting before they read the list.
Each permission is a verb phrase with a quiet detail line. Required ones are checked and locked; optional ones can be switched off. Permissions that can change data are marked with a pencil and words. Under the list, one sentence says what the assistant will be able to do and what it will not, and it updates as the choices change. Connect counts the permissions it grants, and onConnect receives their ids.
Move status to authorizing while the sign-in window is open: the card says what to do and offers to open the window again or cancel. connected lists what was granted with Disconnect; expired asks to sign in again; error shows your error text with the fix and a retry. The provider mark is yours to pass as service.mark; the kit ships no brand logos. Render it inside the card your host draws for a widget answer. It fills the width it is given, so a comfortable max width (around 28 rem) comes from the card, and it follows the host theme through the kit tokens. Pass onExpand where the host can go full screen.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
service | { name, host, mark?, publisher?, verified? } | The server |
reason | ReactNode | Why the assistant asks |
scopes | { id, label, detail?, access?, required? }[] | access: "write" marks changes |
value, defaultValue, onValueChange | string[] | Granted optional ids. Default all |
status | "loading" | "idle" | "authorizing" | "connected" | "error" | "expired" | Default idle |
onConnect | (scopeIds) => void | The primary action |
onDecline, onReopen, onCancel, onDisconnect | () => void | |
account, error | ReactNode | Connected account; error text with the fix |
disabled | boolean | |
labels | Partial<…Labels> | Every string the widget writes, for translation |
Labels
labels covers the title (title(name)), trust lines, the permission marks, the sentence (summary(granted), notGranted(names)), the connect button (connect(count)), the waiting copy, connected and expired lines and join for lists.
Keyboard
| Key | Action |
|---|---|
| Tab | Optional permissions, then Not now and Connect |
| Space | Grant or withhold the focused permission |
Accessibility
- Permissions are native checkboxes in a fieldset described by the summary sentence, so a screen reader hears the outcome with the list. Details are linked to each checkbox.
- Required permissions are disabled checked boxes with a Required label, not hidden.
- Trust and change marks always carry words next to their icons.
- The summary is a polite live region; waiting, connected and expired are status messages.
Motion
Checks fill in 150 ms. The connected and expired lines enter with a 220 ms fade from 0.96. Reduced motion keeps the fades only.