Connector setup
ProA "Connect your tools" card for an AI assistant. Each app connects inline: it redirects, authorizes and runs a first sync with a progress hairline, then lists the scopes it was granted and offers Disconnect with an inline confirm.
Connect your tools
Let Claude search and act in the apps your team uses.
- SlackSearch channels and threads, post replies
- GitHubnorthwind-labs · 342 pull requests
- NotionSearch pages, docs and databases
- Google Drivemaya@northwind.co · 5,612 files
- LinearCreate, triage and update issues
- JiraTrack tickets across Atlassian projects
- SalesforceLook up accounts and opportunities
- HubSpotRead contacts, deals and notes
- An assistant's settings or onboarding step where people connect workspace apps.
- A first-run checklist that needs to show the OAuth handshake and first sync inline, without leaving the page.
- Reviewing which scopes an assistant holds per app and revoking them.
- Browsing dozens of integrations by category: use the integrations-grid block.
- Approving a single action the agent wants to take: use agent-approvals.
- Showing a tool the agent is calling right now: use tool-call.
Installation
Pro source and install commands unlock with a Pro plan.
import { ConnectorSetup } from "@/components/arc/connector-setup/connector-setup"; export function Integrations({ connectedIds }: { connectedIds: string[] }) { return ( <ConnectorSetup defaultConnected={connectedIds} connect={async (app, { signal, report }) => { const popup = await openOAuthPopup(app.id, { signal }); report({ phase: "authorizing" }); const grant = await popup.result; report({ phase: "syncing", synced: 0 }); const { total } = await startFirstSync(app.id, grant, { signal, onProgress: synced => report({ synced }) }); return { account: grant.workspace, scopes: grant.scopes, synced: total }; }} disconnect={(app, { signal }) => revokeGrant(app.id, { signal })} onConnectedChange={ids => saveConnectedApps(ids)} /> );}API reference
2 parts. The first is the root.
ConnectorSetup
A "Connect your tools" card for an AI assistant. Each app connects inline through redirect, authorize and first sync with a progress line, then lists the scopes it granted with a Disconnect option. With no props it renders eight sample apps and plays a short scripted run.
connectorsConnector[]connectorSamplesApps to list: { id, name, description, mark, host?, account?, scopes?, sync?: { count, noun }, keywords? }. `mark` is a built-in id (slack, github, notion, google-drive, linear, jira, salesforce, hubspot) or your own 20px node.connectedstring[]–Controlled list of connected ids.defaultConnectedstring[]["github", "google-drive"] for the samples, [] otherwiseIds connected on mount when uncontrolled.onConnectedChange(ids: string[]) => void–Called with the new list after a connect or disconnect finishes.connect(connector, { signal, report }) => Promise<ConnectResult | void>–Runs your real OAuth flow. Call report({ phase: "authorizing" }) and report({ phase: "syncing", synced }) as it advances; throw an Error to show its message with Retry; return { account?, scopes?, synced? } to finish. `signal` aborts on Cancel or unmount. Simulated when omitted.disconnect(connector, { signal }) => Promise<void>–Revokes access after the inline confirmation. Simulated when omitted.onConnect(connector: Connector, result: ConnectResult) => void–Called once a connection completes, with the account, scopes and sync count.onDisconnect(connector: Connector) => void–Called once access is revoked.assistantNamestring"Claude"Used in the description, the scopes heading and the footer.titleReactNode"Connect your tools"Card heading.descriptionReactNode"Let Claude search and act in the apps your team uses."Line under the heading.searchablebooleantrueShows the search field. It matches name, description, account and keywords.searchPlaceholderstring"Search apps"Placeholder for the search field.autoPlaybooleantrue for the samples without connectPlays a scripted run once the card is on screen: connect Slack, then a Salesforce attempt that needs admin approval and its retry. Stops at the first pointer or key press.footerReactNode–Footer line under the list. Defaults to a short privacy note; pass null to hide it.classNamestring–Class on the root card.ConnectorMark
The built-in app marks at any size, for use elsewhere in your settings UI.
markRequiredConnectorMarkId | ReactNode–A built-in id or your own node.sizenumber20Rendered size in px.- Tab
- Moves through search, each row's Connect, Cancel, Retry or Connected button, and the open details.
- EnterorSpace
- Connects, cancels, retries, or opens and closes a connected app's access details.
- Escape
- Clears the search field, or backs out of the disconnect confirmation.
- The card is a labelled group with a real heading; the list is a ul with one li per app.
- A polite live region announces each step: connecting, connected with the sync count, failed with the reason, cancelled and disconnected. With the built-in simulation it adds "Simulated, nothing was sent."
- Status is never color alone: errors pair an alert icon with the message, connected apps show a check with the word Connected.
- The Connected button carries aria-expanded and aria-controls for the details region; Disconnect asks for confirmation and focuses the destructive button only after a deliberate press.
- Content that is fading out leaves the accessibility tree and stops taking clicks immediately.
- Status lines and actions swap with one crossfade (out 100ms, in 160ms with a 2px rise) in a shared grid cell, so the row never reflows.
- Progress is a 2px hairline that eases between steps and tracks the sync count linearly; the count rolls in tabular numerals inside a width reserved for its final value.
- Details open with a bounce-free spring on measured height (visualDuration 0.24).
- The scripted run starts only once the card is on screen and stops at the first interaction. Reduced motion keeps every state and announcement but cuts the crossfades and height springs.
- Fluid up to 520px and holds at 360px: names and status lines truncate with an ellipsis while marks and actions keep their size.
- Actions stay 32px tall with full-width rows of 60px, comfortable for touch.
- The details column aligns to the row's text at every width; the disconnect confirmation truncates its question before it wraps.
- Pure React and CSS with a few Motion components; marks are inline SVG with no image requests.
- Only the row that is syncing re-renders per frame while its count rolls; other rows stay static.
- Search filters in memory; for hundreds of apps, filter on your side and pass the result as connectors.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use for onboarding or settings screens where a person grants an assistant access to third-party apps. Pass your own connectors; built-in marks cover Slack, GitHub, Notion, Google Drive, Linear, Jira, Salesforce and HubSpot.
- Wire connect to your OAuth popup or redirect handshake and call report() at each step so the row shows real progress; throw an Error with a short human message ("Needs admin approval") to show Retry.
- Write scopes as plain-language capabilities ("Post replies as Claude"), not raw OAuth scope strings.
- Keep it one card in a settings column. For a full marketplace grid of integrations use the integrations-grid block instead.
The full library index for assistants is at /llms.txt.