@cantera/acc-connection-panelblock
The live Autodesk connection panel: one ConnectionCard wired to a sign-out route and a consent restart, with disconnect and reconnect on the async-pending contract.
npx shadcn@latest add @cantera/acc-connection-panelOne ConnectionCard bound to two hrefs: signOutHref takes a POST that clears the grant and session, signInHref restarts consent. Disconnect settles by refreshing the server page, so the server view stays the truth; reconnect navigates. @cantera/acc-sign-in mounts it under a heading once a session exists.
| Prop | Type | Description |
|---|---|---|
| connection | OAuthConnection | The Autodesk grant to render — status, account, scopes, expiry. |
| signOutHref | string | POST target that clears the grant and session, e.g. "/api/auth/signout?next=/sign-in". Disconnect settles by refreshing the server page. |
| signInHref | string | GET target that restarts consent, e.g. "/api/auth/aps?next=/sign-in". Reconnect navigates there and keeps its spinner until the page changes. |
This is the exact code the CLI installs into your project — you own it from there.
'use client'
import { useRouter } from 'next/navigation'
import { useState, useTransition } from 'react'
import { ConnectionCard } from '@/components/ui/connection-card'
import type { OAuthConnection } from '@/lib/oauth-types'
interface AccConnectionPanelProps {
connection: OAuthConnection
/** POST target that clears the grant and session, e.g. "/api/auth/signout?next=/sign-in". */
signOutHref: string
/** GET target that restarts consent, e.g. "/api/auth/aps?next=/sign-in". */
signInHref: string
}
function AccConnectionPanel({ connection, signOutHref, signInHref }: AccConnectionPanelProps) {
const router = useRouter()
const [disconnecting, setDisconnecting] = useState(false)
const [reconnecting, setReconnecting] = useState(false)
const [, startRefresh] = useTransition()
async function disconnect() {
setDisconnecting(true)
try {
await fetch(signOutHref, { method: 'POST', redirect: 'manual' })
} finally {
// Pending clears inside the transition so the button keeps its spinner
// until the re-rendered server page commits; refresh runs on failure too.
startRefresh(() => {
router.refresh()
setDisconnecting(false)
})
}
}
return (
<ConnectionCard
connection={connection}
// The handler is always passed: pending is a prop, never an absent
// callback, so the pressed button stays mounted through the request.
onDisconnect={disconnect}
disconnectPending={disconnecting}
onReconnect={() => {
setReconnecting(true)
window.location.href = signInHref
}}
reconnectPending={reconnecting}
/>
)
}
export { AccConnectionPanel, type AccConnectionPanelProps }