AuthForm

A customizable Form to create login, register or password reset forms.

Usage

Built on top of the Form component, the AuthForm component can be used in your pages or wrapped in a PageCard.

The form will construct itself based on the fields prop and the state will be handled internally. You can pass all the props you would pass to a FormField or an Input to each field.

Login
Enter your credentials to access your account.
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'

const toast = useToast()

const fields = [{
  name: 'email',
  type: 'text' as const,
  label: 'Email',
  placeholder: 'Enter your email',
  required: true
}, {
  name: 'password',
  label: 'Password',
  type: 'password' as const,
  placeholder: 'Enter your password'
}, {
  name: 'remember',
  label: 'Remember me',
  type: 'checkbox' as const
}]

const providers = [{
  label: 'Google',
  icon: 'i-simple-icons-google',
  onClick: () => {
    toast.add({ title: 'Google', description: 'Login with Google' })
  }
}, {
  label: 'GitHub',
  icon: 'i-simple-icons-github',
  onClick: () => {
    toast.add({ title: 'GitHub', description: 'Login with GitHub' })
  }
}]

const schema = z.object({
  email: z.string().email('Invalid email'),
  password: z.string().min(8, 'Must be at least 8 characters')
})

type Schema = z.output<typeof schema>

function onSubmit(payload: FormSubmitEvent<Schema>) {
  console.log('Submitted', payload)
}
</script>

<template>
  <div class="flex flex-col items-center justify-center gap-4 p-4">
    <UPageCard class="w-full max-w-md">
      <UAuthForm
        :schema="schema"
        title="Login"
        description="Enter your credentials to access your account."
        icon="i-lucide-user"
        :fields="fields"
        :providers="providers"
        @submit="onSubmit"
      />
    </UPageCard>
  </div>
</template>

Title

Use the title prop to set the title of the form.

Login
<script setup lang="ts">
const fields = ref([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm class="max-w-md" title="Login" :fields="fields" />
</template>

Description

Use the description prop to set the description of the form.

Login
Enter your credentials to access your account.
<script setup lang="ts">
const fields = ref([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    class="max-w-md"
    title="Login"
    description="Enter your credentials to access your account."
    :fields="fields"
  />
</template>

Icon

Use the icon prop to set the icon of the form.

Login
Enter your credentials to access your account.
<script setup lang="ts">
const fields = ref([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    class="max-w-md"
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :fields="fields"
  />
</template>

Providers

Use the providers prop to add providers to the form.

You can pass any property from the Button component such as variant, color, to, etc.

Login
Enter your credentials to access your account.
<script setup lang="ts">
const fields = ref([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
const providers = ref([
  {
    label: 'Google',
    icon: 'i-simple-icons-google',
    color: 'neutral',
    variant: 'subtle'
  },
  {
    label: 'GitHub',
    icon: 'i-simple-icons-github',
    color: 'neutral',
    variant: 'subtle'
  }
])
</script>

<template>
  <UAuthForm
    class="max-w-md"
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :providers="providers"
    :fields="fields"
  />
</template>

Separator

Use the separator prop to customize the Separator between the providers and the fields. Defaults to or.

Login
Enter your credentials to access your account.
<script setup lang="ts">
const providers = ref([
  {
    label: 'Google',
    icon: 'i-simple-icons-google',
    color: 'neutral',
    variant: 'subtle'
  },
  {
    label: 'GitHub',
    icon: 'i-simple-icons-github',
    color: 'neutral',
    variant: 'subtle'
  }
])
const fields = ref([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    class="max-w-md"
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :providers="providers"
    :fields="fields"
    separator="Providers"
  />
</template>

You can pass any property from the Separator component to customize it.

Login
Enter your credentials to access your account.
<script setup lang="ts">
const providers = ref([
  {
    label: 'Google',
    icon: 'i-simple-icons-google',
    color: 'neutral',
    variant: 'subtle'
  },
  {
    label: 'GitHub',
    icon: 'i-simple-icons-github',
    color: 'neutral',
    variant: 'subtle'
  }
])
const fields = ref([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    class="max-w-md"
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :providers="providers"
    :fields="fields"
    :separator="{
      icon: 'i-lucide-user'
    }"
  />
</template>

Submit

Use the submit prop to change the submit button of the form.

You can pass any property from the Button component such as variant, color, to, etc.

Login
Enter your credentials to access your account.
<script setup lang="ts">
const fields = ref([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    class="max-w-md"
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :fields="fields"
    :submit="{
      label: 'Submit',
      color: 'error',
      variant: 'subtle'
    }"
  />
</template>

Examples

Within a page

You can wrap the AuthForm component with the PageCard component to display it within a login.vue page for example.

Welcome back!
Don't have an account? Sign up.
Error signing in
By signing in, you agree to our Terms of Service.
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'

const toast = useToast()

const fields = [{
  name: 'email',
  type: 'text' as const,
  label: 'Email',
  placeholder: 'Enter your email',
  required: true
}, {
  name: 'password',
  label: 'Password',
  type: 'password' as const,
  placeholder: 'Enter your password'
}, {
  name: 'remember',
  label: 'Remember me',
  type: 'checkbox' as const
}]

const providers = [{
  label: 'Google',
  icon: 'i-simple-icons-google',
  onClick: () => {
    toast.add({ title: 'Google', description: 'Login with Google' })
  }
}, {
  label: 'GitHub',
  icon: 'i-simple-icons-github',
  onClick: () => {
    toast.add({ title: 'GitHub', description: 'Login with GitHub' })
  }
}]

const schema = z.object({
  email: z.string().email('Invalid email'),
  password: z.string().min(8, 'Must be at least 8 characters')
})

type Schema = z.output<typeof schema>

function onSubmit(payload: FormSubmitEvent<Schema>) {
  console.log('Submitted', payload)
}
</script>

<template>
  <div class="flex flex-col items-center justify-center gap-4 p-4">
    <UPageCard class="w-full max-w-md">
      <UAuthForm
        :schema="schema"
        :fields="fields"
        :providers="providers"
        title="Welcome back!"
        icon="i-lucide-lock"
        @submit="onSubmit"
      >
        <template #description>
          Don't have an account? <ULink to="#" class="text-(--ui-primary) font-medium">Sign up</ULink>.
        </template>

        <template #password-hint>
          <NuxtLink to="/" class="text-(--ui-primary) font-medium">Forgot password?</NuxtLink>
        </template>
        <template #validation>
          <UAlert color="error" icon="i-lucide-info" title="Error signing in" />
        </template>
        <template #footer>
          By signing in, you agree to our <ULink to="#" class="text-(--ui-primary) font-medium">Terms of Service</ULink>.
        </template>
      </UAuthForm>
    </UPageCard>
  </div>
</template>

API

Props

Prop Default Type
as

'div'

any

The element or component this component should render as.

title

string

description

string

icon

string

fields

AuthFormField[]

providers

ButtonProps[]

Display a list of Button under the description. { color: 'neutral', variant: 'subtle', block: true }

separator

'or'

string | SeparatorProps

The text displayed in the separator.

submit

ButtonProps

Display a submit button at the bottom of the form. { label: 'Continue', block: true }

schema

ZodType<any, ZodTypeDef, any> | GenericSchema<unknown, unknown, BaseIssue<unknown>> | GenericSchemaAsync<unknown, unknown, BaseIssue<unknown>> | (input: unknown): SafeParseResult<any> | (input: unknown): Promise<SafeParseResult<any>> | Struct<any, any> | StandardSchemaV1<unknown, unknown> | AnySchema<any> | ArraySchema<any> | AlternativesSchema<any> | BinarySchema<any> | BooleanSchema<any> | DateSchema<any> | FunctionSchema<any> | NumberSchema<any> | ObjectSchema<any> | StringSchema<any> | LinkSchema<any> | SymbolSchema<any> | ObjectSchema<any, AnyObject, any, "">

validate

(state: object): FormError<string>[] | Promise<FormError<string>[]>

validateOn

FormInputEvents[]

validateOnInputDelay

number

disabled

boolean

ui

Partial<{ root: string; header: string; leading: string; leadingIcon: string; title: string; description: string; body: string; providers: string; separator: string; form: string; footer: string; }>

Slots

Slot Type
header

{}

leading

{}

title

{}

description

{}

validation

{}

footer

{}

Emits

Event Type
submit

[payload: FormSubmitEvent<any>]

Theme

app.config.ts
export default defineAppConfig({
  uiPro: {
    authForm: {
      slots: {
        root: 'w-full space-y-6',
        header: 'flex flex-col text-center',
        leading: 'mb-2',
        leadingIcon: 'size-8 shrink-0',
        title: 'text-xl text-pretty font-semibold text-(--ui-text-highlighted)',
        description: 'mt-1 text-base text-pretty text-(--ui-text-muted)',
        body: 'gap-y-6 flex flex-col',
        providers: 'space-y-3',
        separator: '',
        form: 'space-y-5',
        footer: 'text-sm text-center text-(--ui-text-muted) mt-2'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      uiPro: {
        authForm: {
          slots: {
            root: 'w-full space-y-6',
            header: 'flex flex-col text-center',
            leading: 'mb-2',
            leadingIcon: 'size-8 shrink-0',
            title: 'text-xl text-pretty font-semibold text-(--ui-text-highlighted)',
            description: 'mt-1 text-base text-pretty text-(--ui-text-muted)',
            body: 'gap-y-6 flex flex-col',
            providers: 'space-y-3',
            separator: '',
            form: 'space-y-5',
            footer: 'text-sm text-center text-(--ui-text-muted) mt-2'
          }
        }
      }
    })
  ]
})