Skip to content

<UserButton />

User button with its account menu open, showing the user's name, email and a Sign out button

<UserButton /> is the account control for your app header. Signed-out visitors see a Sign in button that opens <SignIn /> in a dialog. Signed-in users see their avatar, which opens a menu with their name and email, a link to their profile and <SignOutButton />.

Quick start

The base registry item already mounts it in the header of the root layout. To place it elsewhere, render it inside the same providers:

src/routes/+layout.svelte
src/app/layout.tsx

In SvelteKit, the component reads api, authClient and authConstants from an <AuthProvider> ancestor, which the base src/routes/+layout.svelte provides.

In Next.js, the component needs the ConvexClientProvider that the base src/app/layout.tsx mounts.

The profile link opens a dialog only while <UserProfileHost /> is mounted, which the base layouts also do.

What it does

StateRenders
Signed outA Sign in button, or your signInTrigger. It opens <SignIn /> in a dialog.
Session loading, or signed in while the user loadsA circular placeholder the size of the avatar.
Signed inThe user’s avatar. Without an uploaded image, a generated avatar based on the user’s name.

Selecting the avatar opens a menu with the name and email, which open the profile, and Sign out.

Signing in through the dialog closes it and keeps the visitor on the current page, unless the URL has a redirectTo query parameter (see Redirects). The sign-in form starts fresh at the email step each time the dialog opens.

Props

  • popoverPlacement sets where the account menu opens relative to the avatar.
  • initialData takes the user loaded on the server, so the avatar renders on first paint instead of after the client query. The types come from #lib/auth/types.js. The base/ssr item’s src/routes/+layout.server.ts returns this data as data.initialData.
  • signInTrigger replaces the signed-out button. Call open to show the sign-in dialog. It takes a snippet.It takes a render function.

Custom sign-in trigger

Use signInTrigger when the header has no room for a text button, for example in a narrow rail:

src/routes/+layout.svelte
src/components/AccountControl.tsx

An icon-only trigger needs an accessible name such as aria-label="Sign in". Pair it with a visible tooltip on hover and keyboard focus: the label names the control for assistive technology but doesn’t explain an unfamiliar icon to sighted visitors.

Behavior

The profile entry adds ?dialog=user-profile to the URL as a new history entry. <UserProfileHost /> opens the dialog for that parameter, so a reload keeps it open and the browser’s back button closes it.

The avatar, name and email come from the Convex query api.users.queries.getActiveUser, so they update as soon as the user changes them in the profile.