SignupForm

A ready-made account-creation form — name/email/password/confirm fields, a live password-strength checklist, and a required terms checkbox — emits `submit` with the collected values instead of calling an API itself.

vue
<UiSignupForm />

Options

One block per prop — what it does, and what it looks like set.

Loading

loading disables every field and swaps the submit button's label and icon for a spinner, for while the request is in flight.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Error

error is shown above the fields — where a failed signup belongs, since it's about the attempt rather than about any one input.

Create an account

Start your workspace in under a minute.

That email is already in use.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Purely presentational — it validates the fields client-side and emits submit with the raw values, but never calls an API itself. Wire @submit to your own registration request, and set loading/error from its result.

Color

color applies to the submit button and the links, so the whole form picks up one accent.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Title

title is the heading. An empty string drops it, for a form inside a page or modal that already has one.

Join Acme

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Description

description is the line under the heading — the one place to make the promise specific to your product. An empty string drops it.

Join Acme

Free for 30 days, no card needed.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Login to

loginTo is where 'Sign in' points, /login by default. An empty string drops the line.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Terms to

termsTo is the Terms of Service link. Set it to an empty string and the words stay in the sentence but stop being a link — which is what you want before the page exists, rather than shipping a 404 into your consent copy.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Privacy to

privacyTo is the same for the Privacy Policy link.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Providers

providers adds social sign-up under the submit button — a labelled rule, then one button per provider, rendered by SocialLogin with a 'Sign up with …' label. Clicking one emits provider with its id and nothing else happens: the OAuth flow is yours to start. Note that a provider account skips the terms checkbox entirely, so record that consent in your own callback if you need it.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

or

Already have an account? Sign in

A provider button bypasses the whole form, terms checkbox included — nothing here records that consent. If you need it, gate the OAuth flow behind your own check in the provider handler, or capture it on the callback route.

The buttons read 'Sign up with …' rather than SocialLogin's neutral 'Continue with …'. The flow itself is identical either way — OAuth signs in an existing account and creates a missing one with the same redirect — so the wording is a promise about the screen, not about what happens.

Provider layout

providerLayout picks between the full-width labelled buttons above (stacked) and one icon-only button per provider on a single row (inline) — worth the switch once you're offering four or more.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

or

Already have an account? Sign in


Examples

The component in real use: compositions that answer "how do I build X with this", rather than one prop at a time.

Translating the rest — a locale, not thirty props

Every other string comes from the locale handed to App. The consent sentence is five separate keys so it can be reordered per language — German closes the clause after the links with termsSuffix, where English leaves it empty. See [Internationalization](/i18n).

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

`terms` slot — when the sentence won't come apart

Where five fragments still aren't enough — a language that reorders the clause around the links, or copy that needs a third link — the slot replaces the whole sentence and the fragments stop being consulted.

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

Basic — live password requirements, confirm-password match check, required terms checkbox

Create an account

Start your workspace in under a minute.

  • At least 8 characters
  • One uppercase letter
  • One lowercase letter
  • One number

Already have an account? Sign in

The password field sets PasswordInput's min-length/require-uppercase/require-lowercase/require-number — its live checklist is what drives this form's own password validity, tracked via v-model:valid rather than re-implemented here. require-special-char is deliberately left off; add it yourself (and update the submit-time check) if your backend requires it.

'Confirm password' is a plain Input, not another PasswordInput — it doesn't get its own reveal toggle or requirements checklist, it's just checked against password on submit.

The 'Sign in' and terms/privacy links point to /login, /terms, and /privacy — plain hardcoded routes, not props. Add matching pages in your app, or copy the component and change the links if yours differ.


API Reference

Generated from the component's source — props, slots and emits as the component actually declares them.

Props

Prop
Type
Default
Description
boolean
false
Disables the form and shows a loading state on the submit button, e.g. while a request is in flight.
string
—
Server/API error message shown above the fields (e.g. "Email already in use").
"neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending"
'primary'
The color applied to the submit button and the links.
string
—
The heading above the fields. Defaults to "Create an account", or to the app's `bundyUI.signupForm.title` translation. Pass an empty string to drop it.
string
—
The line under the heading. Same defaulting as `title`; an empty string drops it.
string
'/login'
Where "Sign in" goes. Set it to an empty string to drop that line entirely.
string
'/terms'
Where the Terms of Service link goes. Set it to an empty string to leave the words unlinked — better than pointing at a page that doesn't exist yet.
string
'/privacy'
Where the Privacy Policy link goes. Set it to an empty string to leave the words unlinked.
(SocialProviderId | SocialProvider)[]
[]
Social sign-up providers offered under the submit button, via `SocialLogin` — built-in ids like `'google'`, or your own `{ id, name, logo }` objects. Empty by default, so the form is email/password only until you pass some. Their buttons read 'Sign up with …'.
"stacked" | "inline"
'stacked'
How those provider buttons are arranged: 'stacked' full-width labelled rows, or 'inline' icon-only buttons side by side.

Slots

Slot
terms

Emits

Event
Payload
Description
submit
[payload: { name: string; email: string; password: string }]
Fires once the fields pass client-side validation.
provider
[id: string]
Fires when one of the `providers` buttons is clicked, with that provider's `id`.

Types

ts
type Color = "neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending";
ts
interface SocialProvider {
    /**
     * Identifier emitted by `select` — use it in your handler to pick which OAuth flow to start.
     * Matching a `SocialProviderId` also supplies the brand name and logo for free.
     */
    id: string;

    /**
     * The provider's brand name, rendered after the `label` verb ('Continue with **Google**').
     * Defaults to the brand name for a built-in id, or the id itself, title-cased.
     */
    name?: string;

    /**
     * URL of the provider's logo, rendered as an `<img>`. Defaults to the bundled brand mark for a
     * built-in id.
     */
    logo?: string;

    /**
     * A bundled icon name to render instead of a logo image — for a provider with no brand mark of
     * its own (SAML, a magic link, your own SSO).
     */
    icon?: string;
}
ts
type SocialProviderId = "google" | "apple" | "microsoft" | "github" | "gitlab" | "facebook" | "discord" | "x" | "twitter" | "instagram";