Invite chooser
ProShown at sign-in when more than one account has invited you. Pick one to join; the others are superseded and will show as expired. Or create your own account instead, which supersedes them all. Nothing happens until you choose.
Preview
Install
With the Candor CLI
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/invite-chooser
Brings in: button, locale, relative-time, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import { InviteChooser, type IncomingInvite } from "@/components/invite-chooser"
const inDays = (d: number) => new Date(Date.now() + d * 86_400_000).toISOString()
const invites: IncomingInvite[] = [
{ id: "inv-1", account: "Acme", invitedBy: "Priya", grants: ["Contributor on Acme API Staging"], expiresAt: inDays(5) },
{ id: "inv-2", account: "Acme Labs", invitedBy: "Dana", grants: [], expiresAt: inDays(1) },
]
export default function Example() {
// Nothing is chosen until the person picks an invite.
return <InviteChooser invites={invites} onJoin={() => {}} onCreateOwn={() => {}} />
}<InviteChooser>
| Prop | Type | Default | Description |
|---|---|---|---|
| invitesrequired | IncomingInvite[] | — | The invites waiting for this person, one per account. |
| onJoinrequired | (id: string) => void | — | Called with the chosen invite's id when the person joins. |
| onCreateOwn | (() => void) | undefined | — | Shows a link to create their own account instead; called when it's clicked. |
| busy | boolean | undefined | false | Disables Join while it's being recorded. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under inviteChooser in <LocaleProvider strings={{ … }}>; the table is exported as inviteChooserStrings.
| Key | English |
|---|---|
| heading | { one: "{count} account has invited you", other: "{count} accounts have invited you" } |
| belongToOne | { one: "You can belong to one. Joining it supersedes the other invite.", other: "You can belong to one. Joining it supersedes the other invites.", } |
| from | From {name} · expires {expires} |
| noRoles | No roles yet |
| join | Join {account} |
| choose | Choose an account |
| createOwn | Create my own account instead |
Types
- IncomingInvite
{ id: string account: string invitedBy: string /** What joining gives, e.g. ["Editor on Shop staging"]. */ grants: string[] expiresAt: string }