Skip to content
SLICES / TECHNICAL FOLIO Nº 001FULL-STACK ASSEMBLIES — OPEN SOURCE

Headless / Organizations

Invitations

Collect several email addresses, resolve invalid entries, and send invitations together.

37 public parts · 2examples

@slices.sh/auth/headlessView as Markdown ↗

Your design. Our behavior.

Explore the tree to see what each part controls. Gates reveal the relevant state; roots outline their scope.

Behavior / inputGateGenericRenderer · not headlessScope
COMPONENT ANATOMYHover · focus · tap
ONE POSSIBLE DESIGNStatic preview

User.Root · Scope

User.RootSays 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.

Installation

Choose what your component needs. Run these commands in an initialized Next.js app.

0

Before you start

The steps below run in a Next.js app with shadcn set up (it has a components.json). In an existing Next.js app, such as one from create-next-app, set shadcn up first:

npx shadcn@latest init -t next -b base -p nova

Or start fresh: the slices CLI creates the app and sets it up.

npx slices.sh install
1

Install the service registry

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

npx add services
2

Install the headless library

npm

Add the React parts to your app, then compose them with your own elements.

npm install @slices.sh/auth@^0.1.10

Import from @slices.sh/auth/headless.

3

Install the service

Connect the parts to a provider. Skip this step if this service is already configured in your app.

Provider
Database
Authentication methods
Account capabilities
npx add auth.betterauth --auth-methods google --organizations

Adds service configuration and API routes to your app, with the provider dependencies. For a headless composition, add import "@/services" after "use client".

The slices CLI installs the service and provisions its required resources in one command.

Set BETTER_AUTH_URL to your app origin. Memory is for local development; use a persistent database for deployment. Neon and Supabase also require the migration script printed by the installer.

Provider setup notes
  • BETTER_AUTH_SECRET signs every session and is generated into .env.local while this installs (32 random bytes, base64, nothing leaves the machine). Changing it signs everyone out; in production set the same one on every instance.
  • The public origin (OAuth callbacks, the passkey domain) is the one each request comes to in development, and the deployment's own on Vercel. Elsewhere, or behind a proxy or a custom domain, set BETTER_AUTH_URL, such as https://acme.com.

Start small

Parts bring the behavior. Use their default elements, or supply your own with render.

example.tsx
"use client"import "@/services"import { User, Invite } from "@slices.sh/auth/headless"export function Example() {  return (    <User.Root>      <Invite.Batch.Form>        <Invite.Batch.Label>Email addresses</Invite.Batch.Label>        <Invite.Batch.Input />        <Invite.Batch.Add>Add addresses</Invite.Batch.Add>        <Invite.Batch.List>          <Invite.Batch.Items>            <Invite.Batch.Remove>Remove</Invite.Batch.Remove>          </Invite.Batch.Items>        </Invite.Batch.List>        <Invite.Batch.Submit>Send invitations</Invite.Batch.Submit>        <Invite.Batch.Summary />        <Invite.Batch.Error />      </Invite.Batch.Form>    </User.Root>  )}

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

API reference

Every public part used by this experience is listed below. Gates render children without adding an element. Element parts accept native element props and render; function children receive the state declared in their props. Scopes provide context rather than a visual element.

Members.CancelInvitationErrorcontent · <p>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.CancelInvitationError requires an invitation row.

Props

2 documented props · Native <p> attributes supported

Members.CancelInvitationError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { code: AuthErrorCode; message: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.CancelInvitationError from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/cancel-invitation-error.tsx

Members.RenewInvitationErrorcontent · <p>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.RenewInvitationError requires an invitation row.

Props

2 documented props · Native <p> attributes supported

Members.RenewInvitationError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { code: AuthErrorCode; message: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.RenewInvitationError from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/renew-invitation-error.tsx

Members.RenewInvitationaction · <button>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.RenewInvitation requires an invitation row.

Props

2 documented props · Native <button> attributes supported

Members.RenewInvitation props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean; retryAfter: number }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.RenewInvitation from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/renew-invitation.tsx

Members.InvitationExpirycontent · <time>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.InvitationExpiry requires an invitation row.

Props

2 documented props · Native <time> attributes supported

Members.InvitationExpiry props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { expiresAt: Date | null; expired: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.InvitationExpiry from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/invitation-expiry.tsx

Members.InvitationsErrorcontent · <div>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Props

2 documented props · Native <div> attributes supported

Members.InvitationsError props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { code: AuthErrorCode; message: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.InvitationsError from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/invitations-error.tsx

Members.InvitationsEmptygate

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Props

1 documented props

Members.InvitationsEmpty props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.InvitationsEmpty from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/invitations-empty.tsx

Members.InvitationsLoadinggate

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Props

1 documented props

Members.InvitationsLoading props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.InvitationsLoading from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/invitations-loading.tsx

Members.InvitationCountcontent · <span>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Props

2 documented props · Native <span> attributes supported

Members.InvitationCount props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.InvitationCount from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/invitation-count.tsx

Members.CopyInvitationaction · <button>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.CopyInvitation must be inside <Members.Invitation>.

Props

2 documented props · Native <button> attributes supported

Members.CopyInvitation props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { copied: boolean; error: string | null }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.CopyInvitation from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/copy-invitation.tsx

Members.Invitationcontent · <li>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.Invitation renders its items itself.

Props

2 documented props · Native <li> attributes supported

Members.Invitation props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { role: Role; email: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.Invitation from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/invitation.tsx

Members.InvitationEmailcontent

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.InvitationEmail must be inside <Members.Invitation>.

Props

2 documented props

Members.InvitationEmail props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.InvitationEmail from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/invitation-email.tsx

Members.CancelInvitationaction · <button>

Invitation is an <li> repeated once per pending invitation with { role }; InvitationEmail is its address, InvitationCount the total, InvitationExpiry a <time> with { expiresAt, expired }. CancelInvitation and RenewInvitation act on it, each with its error part, and render nothing when you cannot manage invitations. CopyInvitation copies its link, with { copied, error }. InvitationsLoading, InvitationsEmpty and InvitationsError cover the read.

Required scope

Members.CancelInvitation must be inside <Members.Invitation>.

Members.CancelInvitation requires an invitation row.

Props

2 documented props · Native <button> attributes supported

Members.CancelInvitation props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Members.CancelInvitation from @slices.sh/auth/headless/members

Source: @slices.sh/auth/src/headless/members/cancel-invitation.tsx

Invite.Formaction · <form>

Form holds the address and the role with { pending }. Label takes field="email" | "role". Email is <input type="email" autocomplete="off">, invalid when the address is already a member's. Role is a native <select> starting at member, RoleOption one option per role. Submit is disabled until the address is valid.

Capability: organizations

Props

2 documented props · Native <form> attributes supported

Invite.Form props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Form from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/form.tsx

Invite.NotAllowedgate

Why there is no invitation form here. The mirror of `Invite.Form`, and not a courtesy: a plain member used to get the whole form and, on submitting it, "You don't have permission to do that" — a sentence about them rather than about the organization's rules. Closed while the organization is loading, so nobody is told they are only a member for the half-second before we know. → docs/rules/capability-honesty.md

Capability: organizations

Props

1 documented props

Invite.NotAllowed props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.NotAllowed from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/not-allowed.tsx

Invite.Labelcontent · <label>

Form holds the address and the role with { pending }. Label takes field="email" | "role". Email is <input type="email" autocomplete="off">, invalid when the address is already a member's. Role is a native <select> starting at member, RoleOption one option per role. Submit is disabled until the address is valid.

Capability: organizations

Required scope

Invite.Label must be inside <Invite.Form>.

Props

3 documented props · Native <label> attributes supported

Invite.Label props
PropTypeDefault
fieldRequired
keyof typeof FIELDS—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Label from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/label.tsx

Invite.Emailinput · <input>

Form holds the address and the role with { pending }. Label takes field="email" | "role". Email is <input type="email" autocomplete="off">, invalid when the address is already a member's. Role is a native <select> starting at member, RoleOption one option per role. Submit is disabled until the address is valid.

Capability: organizations

Required scope

Invite.Email must be inside <Invite.Form>.

Props

2 documented props · Native <input> attributes supported

Invite.Email props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { invalid: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Email from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/email.tsx

Invite.Roleinput · <select>

Form holds the address and the role with { pending }. Label takes field="email" | "role". Email is <input type="email" autocomplete="off">, invalid when the address is already a member's. Role is a native <select> starting at member, RoleOption one option per role. Submit is disabled until the address is valid.

Capability: organizations

Required scope

Invite.Role must be inside <Invite.Form>.

Props

2 documented props · Native <select> attributes supported

Invite.Role props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { role: RoleName }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Role from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/role.tsx

Invite.RoleOptioncontent · <option>

Form holds the address and the role with { pending }. Label takes field="email" | "role". Email is <input type="email" autocomplete="off">, invalid when the address is already a member's. Role is a native <select> starting at member, RoleOption one option per role. Submit is disabled until the address is valid.

Capability: organizations

Props

2 documented props · Native <option> attributes supported

Invite.RoleOption props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { role: Role }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.RoleOption from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/members/role-option.tsx

Invite.Submitaction · <button>

Form holds the address and the role with { pending }. Label takes field="email" | "role". Email is <input type="email" autocomplete="off">, invalid when the address is already a member's. Role is a native <select> starting at member, RoleOption one option per role. Submit is disabled until the address is valid.

Capability: organizations

Required scope

Invite.Submit must be inside <Invite.Form>.

Props

2 documented props · Native <button> attributes supported

Invite.Submit props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Submit from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/submit.tsx

Invite.Sentgate

Sent opens with { email } after a successful invite, until the form changes. Error is <div role="alert"> with { code, message }.

Required scope

Invite.Sent must be inside <Invite.Form>.

Props

1 documented props

Invite.Sent props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { email: string; id: string }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Sent from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/sent.tsx

Invite.Errorcontent · <div>

Sent opens with { email } after a successful invite, until the form changes. Error is <div role="alert"> with { code, message }.

Props

2 documented props · Native <div> attributes supported

Invite.Error props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { code: AuthErrorCode; message: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Error from @slices.sh/auth/headless/invite

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

Invite.Batch.Expirycontent · <time>

CopyLink copies the organization's invite link, disabled once it expired. Expiry is a <time> with { expiresAt, expired }.

Required scope

Invite.Batch.Expiry requires a recipient row.

Props

2 documented props · Native <time> attributes supported

Invite.Batch.Expiry props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { expiresAt: Date | null; expired: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Expiry from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/expiry.tsx

Invite.Batch.Formaction · <form>

Form holds the chips with { pending }. Input takes typed or pasted addresses and turns them into chips on Enter, comma, semicolon or Tab. Label and Hint describe it. Add turns what is typed into chips.

Capability: organizations

Props

2 documented props · Native <form> attributes supported

Invite.Batch.Form props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Form from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/form.tsx

Invite.Batch.Inputinput · <input>

Form holds the chips with { pending }. Input takes typed or pasted addresses and turns them into chips on Enter, comma, semicolon or Tab. Label and Hint describe it. Add turns what is typed into chips.

Capability: organizations

Required scope

Invite.Batch.Input must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <input> attributes supported

Invite.Batch.Input props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Input from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/input.tsx

Invite.Batch.Labelcontent · <label>

Form holds the chips with { pending }. Input takes typed or pasted addresses and turns them into chips on Enter, comma, semicolon or Tab. Label and Hint describe it. Add turns what is typed into chips.

Capability: organizations

Required scope

Invite.Batch.Label must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <label> attributes supported

Invite.Batch.Label props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Label from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/label.tsx

Invite.Batch.Hintcontent · <p>

Form holds the chips with { pending }. Input takes typed or pasted addresses and turns them into chips on Enter, comma, semicolon or Tab. Label and Hint describe it. Add turns what is typed into chips.

Capability: organizations

Required scope

Invite.Batch.Hint must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <p> attributes supported

Invite.Batch.Hint props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Hint from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/hint.tsx

Invite.Batch.Addaction · <button>

Form holds the chips with { pending }. Input takes typed or pasted addresses and turns them into chips on Enter, comma, semicolon or Tab. Label and Hint describe it. Add turns what is typed into chips.

Capability: organizations

Required scope

Invite.Batch.Add must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <button> attributes supported

Invite.Batch.Add props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Add from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/add.tsx

Invite.Batch.Listcontent · <ul>

List is the <ul>, Items repeats once per chip, Role sets that chip's role, Remove drops it, Problem gets { problem, message } for an invalid or duplicate address.

Required scope

Invite.Batch.List must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <ul> attributes supported

Invite.Batch.List props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.List from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/list.tsx

Invite.Batch.Itemscontent · <li>

List is the <ul>, Items repeats once per chip, Role sets that chip's role, Remove drops it, Problem gets { problem, message } for an invalid or duplicate address.

Required scope

Invite.Batch.Items must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <li> attributes supported

Invite.Batch.Items props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { email: string; created: boolean; invalid: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Items from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/items.tsx

Invite.Batch.Roleinput · <select>

List is the <ul>, Items repeats once per chip, Role sets that chip's role, Remove drops it, Problem gets { problem, message } for an invalid or duplicate address.

Required scope

Invite.Batch.Role must be inside <Invite.Batch.Items>.

Props

2 documented props · Native <select> attributes supported

Invite.Batch.Role props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Role from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/role.tsx

Invite.Batch.Removeaction · <button>

List is the <ul>, Items repeats once per chip, Role sets that chip's role, Remove drops it, Problem gets { problem, message } for an invalid or duplicate address.

Required scope

Invite.Batch.Remove must be inside <Invite.Batch.Items>.

Props

2 documented props · Native <button> attributes supported

Invite.Batch.Remove props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Remove from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/remove.tsx

Invite.Batch.Problemcontent · <p>

List is the <ul>, Items repeats once per chip, Role sets that chip's role, Remove drops it, Problem gets { problem, message } for an invalid or duplicate address.

Required scope

Invite.Batch.Problem must be inside <Invite.Batch.Items>.

Props

2 documented props · Native <p> attributes supported

Invite.Batch.Problem props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { problem: EmailChipProblem | null; message: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Problem from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/problem.tsx

Invite.Batch.Submitaction · <button>

Submit sends them all with { count, pending, retryAfter }. Summary gets { created, failed, pending }. Error gets { code, message }.

Required scope

Invite.Batch.Submit must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <button> attributes supported

Invite.Batch.Submit props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number; pending: boolean; retryAfter: number }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Submit from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/submit.tsx

Invite.Batch.Summarycontent · <p>

Submit sends them all with { count, pending, retryAfter }. Summary gets { created, failed, pending }. Error gets { code, message }.

Required scope

Invite.Batch.Summary must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <p> attributes supported

Invite.Batch.Summary props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { created: number; failed: number; pending: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Summary from @slices.sh/auth/headless/invite

Source: @slices.sh/auth/src/headless/invite/batch/summary.tsx

Invite.Batch.Errorcontent · <div>

Submit sends them all with { count, pending, retryAfter }. Summary gets { created, failed, pending }. Error gets { code, message }.

Required scope

Invite.Batch.Error must be inside <Invite.Batch.Form>.

Props

2 documented props · Native <div> attributes supported

Invite.Batch.Error props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { code: AuthErrorCode; message: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Invite.Batch.Error from @slices.sh/auth/headless/invite

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

User.Rootscope

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.

Props

3 documented props

User.Root props
PropTypeDefault
config

The auth config, a slug from the registry (services/auth/<config>.config.ts). The nearest root's, else "default", when left out.

string—
enabled

Left out or true: required, and missing auth throws. "optional": renders its children and every part inside degrades without auth. false: off. A capability name such as "methods: password": requires auth with it.

Enabled—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • User.Root from @slices.sh/auth/headless/user
  • User.Root from @slices.sh/auth/headless/passkeys
  • User.Root from @slices.sh/auth/headless/two-factor

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

Organization.Activegate

Item is a <button> repeated once per organization with { active, pending }; clicking makes it active. Personal switches to the personal account. Active renders its children with the active organization in scope, and nothing on the personal account; None is its mirror, once the answer is in. Switcher holds the searchable list: Switcher.Surface maps onto a Popover or a Sheet, Switcher.Options, Input, List, Item, Empty and Error search and list, and Switcher.Shortcuts binds keys to switch.

Capability: organizations

Props

1 documented props

Organization.Active props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Alternate public imports
  • Organization.Active from @slices.sh/auth/headless/organization

Source: @slices.sh/auth/src/headless/organization/active.tsx

When something is missing

No service configuration
Install the auth setup below and import "@/services". Required service roots report missing setup; gates do not replace that configuration.
Missing capability or parent scope
Follow each part’s context requirements and the example composition. Capability-aware controls hide when the provider cannot perform their action.
Read the setup guide →