# Connected accounts

Compose connected accounts with the auth service and your own interface.

Import: @slices.sh/auth/headless

Public parts: 18

## Installation

### 1. Install the service registry

services/index.ts, which `import "@/services"` loads. A provider setup writes the same file; skip this if your app has one.

```bash
npx shadcn@latest add "https://slices.sh/r/services.json"
```

### 2. Install the headless library

```bash
npm install @slices.sh/auth@^0.1.10
```

### 3. Install the service

Install the provider configuration via shadcn or the slices CLI. Skip this step if your app already has the service configured. Provider commands and provisioning: https://slices.sh/docs/services/auth.md

## Anatomy

### Composition

```text
User.Root
  Accounts.Root
    Accounts.Available
      Accounts.Item
        Accounts.OnlyMethod
        Accounts.UnlinkDialog
          Accounts.Confirm
          Accounts.Cancel
        Accounts.ActionTrigger
      Accounts.Connect
      Accounts.MethodsError
      Accounts.MethodsRetry
      Accounts.LinkError
      Accounts.CallbackError
      Accounts.ActionError
    Accounts.Loading
    Accounts.Empty
    Accounts.Error
      Accounts.Retry
```

## Minimal composition

```tsx
"use client"

import "@/services"
import { Accounts } from "@slices.sh/auth/headless"

export function Example() {
  return (
    <Accounts.Root>
      <Accounts.Connect>
        {({ provider }) => <>Connect {provider}</>}
      </Accounts.Connect>
      <Accounts.Item>
        <Accounts.ActionTrigger>Disconnect</Accounts.ActionTrigger>
        <Accounts.UnlinkDialog>
          <Accounts.Confirm>Confirm</Accounts.Confirm>
          <Accounts.Cancel>Cancel</Accounts.Cancel>
        </Accounts.UnlinkDialog>
      </Accounts.Item>
      <Accounts.Error />
    </Accounts.Root>
  )
}

```

Requires an authenticated account. Organization controls also require organizations and the appropriate role.

## Complete API reference

### Accounts.Root

scope

Available gates the section where the backend links providers after sign-up.

Import: @slices.sh/auth/headless

Capability: linked-accounts

```tsx
RootProps & AuthRootProps
```

Alternate import: Accounts.Root from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/root.tsx

### Accounts.Available

gate

Available gates the section where the backend links providers after sign-up.

Import: @slices.sh/auth/headless

Capability: linked-accounts

```tsx
GateProps
```

Alternate import: Accounts.Available from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/available.tsx

### Accounts.Loading

gate

Loading, Empty, Error and Retry for the linked accounts; MethodsError and MethodsRetry for the sign-in methods read beside them.

Import: @slices.sh/auth/headless

```tsx
GateProps
```

Alternate import: Accounts.Loading from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/loading.tsx

### Accounts.Empty

gate

Loading, Empty, Error and Retry for the linked accounts; MethodsError and MethodsRetry for the sign-in methods read beside them.

Import: @slices.sh/auth/headless

```tsx
GateProps
```

Alternate import: Accounts.Empty from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/empty.tsx

### Accounts.Error

content · Element: p

Loading, Empty, Error and Retry for the linked accounts; MethodsError and MethodsRetry for the sign-in methods read beside them.

Import: @slices.sh/auth/headless

```tsx
PartProps<"p", { message: string }>
```

Alternate import: Accounts.Error from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/error.tsx

### Accounts.Retry

action · Element: button

Loading, Empty, Error and Retry for the linked accounts; MethodsError and MethodsRetry for the sign-in methods read beside them.

Import: @slices.sh/auth/headless

```tsx
PartProps<"button">
```

Alternate import: Accounts.Retry from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/retry.tsx

### Accounts.MethodsError

content · Element: p

Loading, Empty, Error and Retry for the linked accounts; MethodsError and MethodsRetry for the sign-in methods read beside them.

Import: @slices.sh/auth/headless

```tsx
PartProps<"p", { message: string }>
```

Alternate import: Accounts.MethodsError from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/methods-error.tsx

### Accounts.MethodsRetry

action · Element: button

Loading, Empty, Error and Retry for the linked accounts; MethodsError and MethodsRetry for the sign-in methods read beside them.

Import: @slices.sh/auth/headless

```tsx
PartProps<"button">
```

Alternate import: Accounts.MethodsRetry from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/methods-retry.tsx

### Accounts.Item

content · Element: li

Item repeats once per linked account with { provider, account }. OnlyMethod opens inside the row that is the account's last way in. Connect links a provider, with { provider, pending, retryAfter }. LinkError reports a refused link, CallbackError a provider that came back with an error.

Import: @slices.sh/auth/headless

Capability: methods: oauth

Accounts.Item provides its own scope.

```tsx
Props

type Props = PartProps<
  "li",
  { provider: OAuthProvider; account: string | null }
>
```

Alternate import: Accounts.Item from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/item.tsx

### Accounts.OnlyMethod

gate

Item repeats once per linked account with { provider, account }. OnlyMethod opens inside the row that is the account's last way in. Connect links a provider, with { provider, pending, retryAfter }. LinkError reports a refused link, CallbackError a provider that came back with an error.

Import: @slices.sh/auth/headless

Capability: methods: oauth

```tsx
GateProps
```

Alternate import: Accounts.OnlyMethod from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/only-method.tsx

### Accounts.Connect

action · Element: button

Item repeats once per linked account with { provider, account }. OnlyMethod opens inside the row that is the account's last way in. Connect links a provider, with { provider, pending, retryAfter }. LinkError reports a refused link, CallbackError a provider that came back with an error.

Import: @slices.sh/auth/headless

Capability: methods: oauth

Accounts.Connect requires Accounts.Root.

```tsx
Props

type Props = PartProps<
  "button",
  { provider: OAuthProvider; pending: boolean; retryAfter: number }
>
```

Alternate import: Accounts.Connect from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/connect.tsx

### Accounts.LinkError

content · Element: p

Item repeats once per linked account with { provider, account }. OnlyMethod opens inside the row that is the account's last way in. Connect links a provider, with { provider, pending, retryAfter }. LinkError reports a refused link, CallbackError a provider that came back with an error.

Import: @slices.sh/auth/headless

Capability: methods: oauth

Accounts.LinkError requires Accounts.Root.

```tsx
PartProps<"p", { message: string }>
```

Alternate import: Accounts.LinkError from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/link-error.tsx

### Accounts.CallbackError

content · Element: p

Item repeats once per linked account with { provider, account }. OnlyMethod opens inside the row that is the account's last way in. Connect links a provider, with { provider, pending, retryAfter }. LinkError reports a refused link, CallbackError a provider that came back with an error.

Import: @slices.sh/auth/headless

Capability: methods: oauth

```tsx
PartProps<"p", { message: string }>
```

Alternate import: Accounts.CallbackError from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/callback-error.tsx

### Accounts.UnlinkDialog

content

UnlinkDialog maps onto render={<AlertDialog />}. ActionTrigger arms it, Confirm unlinks with { pending, retryAfter }, Cancel disarms, ActionError gets { message }.

Import: @slices.sh/auth/headless

Accounts.UnlinkDialog requires a connection row.

```tsx
PartProps<null>
```

Alternate import: Accounts.UnlinkDialog from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/unlink-dialog.tsx

### Accounts.ActionTrigger

action · Element: button

UnlinkDialog maps onto render={<AlertDialog />}. ActionTrigger arms it, Confirm unlinks with { pending, retryAfter }, Cancel disarms, ActionError gets { message }.

Import: @slices.sh/auth/headless

Accounts.ActionTrigger requires Accounts.Root.

```tsx
PartProps<"button", { pending: boolean; retryAfter: number }>
```

Alternate import: Accounts.ActionTrigger from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/action-trigger.tsx

### Accounts.Cancel

action · Element: button

UnlinkDialog maps onto render={<AlertDialog />}. ActionTrigger arms it, Confirm unlinks with { pending, retryAfter }, Cancel disarms, ActionError gets { message }.

Import: @slices.sh/auth/headless

Accounts.Cancel requires Accounts.Root.

```tsx
PartProps<"button">
```

Alternate import: Accounts.Cancel from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/cancel.tsx

### Accounts.Confirm

action · Element: button

UnlinkDialog maps onto render={<AlertDialog />}. ActionTrigger arms it, Confirm unlinks with { pending, retryAfter }, Cancel disarms, ActionError gets { message }.

Import: @slices.sh/auth/headless

Accounts.Confirm requires a connection row.

```tsx
PartProps<"button", { pending: boolean; retryAfter: number }>
```

Alternate import: Accounts.Confirm from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/confirm.tsx

### Accounts.ActionError

content · Element: p

UnlinkDialog maps onto render={<AlertDialog />}. ActionTrigger arms it, Confirm unlinks with { pending, retryAfter }, Cancel disarms, ActionError gets { message }.

Import: @slices.sh/auth/headless

Accounts.ActionError requires Accounts.Root.

```tsx
PartProps<"p", { message: string }>
```

Alternate import: Accounts.ActionError from @slices.sh/auth/headless/accounts

Source: @slices.sh/auth/src/headless/accounts/action-error.tsx

### User.Root

scope

Says which auth the User parts below read, and whether they may do without it. The parts need
no root: left out, they read the nearest auth root's config, or "default", and render nothing
without auth. `<User.Root enabled="optional">` is for the one who wants that said in the code.

Import: @slices.sh/auth/headless

```tsx
RootProps & AuthRootProps
```

Alternate import: User.Root from @slices.sh/auth/headless/user

Alternate import: User.Root from @slices.sh/auth/headless/passkeys

Alternate import: User.Root from @slices.sh/auth/headless/two-factor

Source: @slices.sh/auth/src/headless/user/root.tsx
