认证表单

FormGitHub
一个可自定义的表单,用于创建登录、注册或密码重置表单。

用法

AuthForm 组件构建于 Form 组件之上,既可在页面中直接使用,也可以包裹在 PageCard 中。

登录
输入您的凭据以访问您的账户。
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent, AuthFormField } from '@nuxt/ui'

const toast = useToast()

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

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.email('Invalid email'),
  password: z.string('Password is required').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>

字段

Form 将根据 fields 属性自动构建,状态由内部处理。

fields 属性用作对象数组,包含以下属性:

  • name: string
  • type: 'checkbox' | 'select' | 'otp' | 'InputHTMLAttributes['type']'

每个字段都必须包含一个 type 属性,它决定了输入组件及应用的附加属性:checkbox 字段使用 Checkbox 属性,select 字段使用 SelectMenu 属性,otp 字段使用 PinInput 属性,所有其他类型使用 Input 属性。

您还可以将 FormField 组件的任何属性传递给每个字段。

您将被登录保持 30 天。

<script setup lang="ts">
import type { AuthFormField } from '@nuxt/ui'

const fields = ref<AuthFormField[]>([
  {
    name: 'email',
    type: 'email',
    label: 'Email',
    placeholder: 'Enter your email',
    required: true
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password',
    placeholder: 'Enter your password',
    required: true
  },
  {
    name: 'country',
    type: 'select',
    label: 'Country',
    placeholder: 'Select country',
    items: [
      {
        label: 'United States',
        value: 'us'
      },
      {
        label: 'France',
        value: 'fr'
      },
      {
        label: 'United Kingdom',
        value: 'uk'
      },
      {
        label: 'Australia',
        value: 'au'
      }
    ]
  },
  {
    name: 'otp',
    type: 'otp',
    label: 'OTP',
    length: 6,
    placeholder: ''
  },
  {
    name: 'remember',
    type: 'checkbox',
    label: 'Remember me',
    description: 'You will be logged in for 30 days.'
  }
])
</script>

<template>
  <UAuthForm :fields="fields" class="max-w-sm" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { AuthFormField } from '@nuxt/ui'

const fields = ref<AuthFormField[]>([
  {
    name: 'email',
    type: 'email',
    label: 'Email',
    placeholder: 'Enter your email',
    required: true
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password',
    placeholder: 'Enter your password',
    required: true
  },
  {
    name: 'country',
    type: 'select',
    label: 'Country',
    placeholder: 'Select country',
    items: [
      {
        label: 'United States',
        value: 'us'
      },
      {
        label: 'France',
        value: 'fr'
      },
      {
        label: 'United Kingdom',
        value: 'uk'
      },
      {
        label: 'Australia',
        value: 'au'
      }
    ]
  },
  {
    name: 'otp',
    type: 'otp',
    label: 'OTP',
    length: 6,
    placeholder: ''
  },
  {
    name: 'remember',
    type: 'checkbox',
    label: 'Remember me',
    description: 'You will be logged in for 30 days.'
  }
])
</script>

<template>
  <UAuthForm :fields="fields" class="max-w-sm" />
</template>

标题

使用 title 属性设置表单标题。

登录
<script setup lang="ts">
import type { AuthFormField } from '@nuxt/ui'

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

<template>
  <UAuthForm title="Login" :fields="fields" class="max-w-md" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { AuthFormField } from '@nuxt/ui'

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

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

描述

使用 description 属性设置表单描述。

登录
输入您的凭据以访问您的账户。
<script setup lang="ts">
import type { AuthFormField } from '@nuxt/ui'

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

<template>
  <UAuthForm
    title="Login"
    description="Enter your credentials to access your account."
    :fields="fields"
    class="max-w-md"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { AuthFormField } from '@nuxt/ui'

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

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

Icon

使用 icon 属性设置表单图标。

登录
输入您的凭据以访问您的账户。
<script setup lang="ts">
import type { AuthFormField } from '@nuxt/ui'

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

<template>
  <UAuthForm
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :fields="fields"
    class="max-w-md"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { AuthFormField } from '@nuxt/ui'

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

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

第三方提供商

使用 providers 属性为表单添加第三方登录方式。

您可以传递 Button 组件的任何属性,例如 variantcolorto 等。

登录
输入您的凭据以访问您的账户。
<script setup lang="ts">
import type { ButtonProps, AuthFormField } from '@nuxt/ui'

const providers = ref<ButtonProps[]>([
  {
    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<AuthFormField[]>([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :providers="providers"
    :fields="fields"
    class="max-w-md"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ButtonProps, AuthFormField } from '@nuxt/ui'

const providers = ref<ButtonProps[]>([
  {
    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<AuthFormField[]>([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

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

Separator

使用 separator 属性自定义第三方登录与字段之间的 Separator。默认为 or

登录
输入您的凭据以访问您的账户。
<script setup lang="ts">
import type { ButtonProps, AuthFormField } from '@nuxt/ui'

const providers = ref<ButtonProps[]>([
  {
    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<AuthFormField[]>([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :providers="providers"
    :fields="fields"
    separator="Providers"
    class="max-w-md"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ButtonProps, AuthFormField } from '@nuxt/ui'

const providers = ref<ButtonProps[]>([
  {
    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<AuthFormField[]>([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

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

您可以传递 Separator 组件的任何属性来进行自定义。

登录
输入您的凭据以访问您的账户。
<script setup lang="ts">
import type { ButtonProps, AuthFormField } from '@nuxt/ui'

const providers = ref<ButtonProps[]>([
  {
    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<AuthFormField[]>([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

<template>
  <UAuthForm
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :providers="providers"
    :fields="fields"
    :separator="{
      icon: 'i-lucide-user'
    }"
    class="max-w-md"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ButtonProps, AuthFormField } from '@nuxt/ui'

const providers = ref<ButtonProps[]>([
  {
    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<AuthFormField[]>([
  {
    name: 'email',
    type: 'text',
    label: 'Email'
  },
  {
    name: 'password',
    type: 'password',
    label: 'Password'
  }
])
</script>

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

提交

使用 submit 属性更改表单的提交按钮。

您可以传递 Button 组件的任何属性,例如 variantcolorto 等。

登录
输入您的凭据以访问您的账户。
<script setup lang="ts">
import type { AuthFormField } from '@nuxt/ui'

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

<template>
  <UAuthForm
    title="Login"
    description="Enter your credentials to access your account."
    icon="i-lucide-user"
    :fields="fields"
    :submit="{
      label: 'Submit',
      color: 'error',
      variant: 'subtle'
    }"
    class="max-w-md"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { AuthFormField } from '@nuxt/ui'

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

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

示例

在页面内

您可以将 AuthForm 组件包裹在 PageCard 组件中,以便在 login.vue 页面中使用。

欢迎回来!
还没有账户?注册.
登录时出错
登录即表示您同意我们的服务条款.
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent, AuthFormField } from '@nuxt/ui'

const toast = useToast()

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

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.email('Invalid email'),
  password: z.string('Password is required').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-primary font-medium">Sign up</ULink>.
        </template>
        <template #password-hint>
          <ULink to="#" class="text-primary font-medium" tabindex="-1">Forgot password?</ULink>
        </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-primary font-medium">Terms of Service</ULink>.
        </template>
      </UAuthForm>
    </UPageCard>
  </div>
</template>

API

属性

属性默认值类型
as'div'any

此组件应渲染为的元素或组件。

图标any

显示在标题上方的图标。

titlestring
descriptionstring
fieldsF[]
providersButtonProps[]

在描述下方显示按钮列表。{ color: 'neutral', variant: 'subtle', block: true }

separator'or'string | SeparatorProps

分隔符中显示的文本。

submitOmit<ButtonProps, LinkPropsKeys>

在表单底部显示提交按钮。{ label: 'Continue', block: true }

schemaT
validate(state: Partial<InferInput<T>>): FormError<string>[] | Promise<FormError<string>[]>
validateOnFormInputEvents[]
validateOnInputDelaynumber
disabledboolean
loadingboolean
loadingAutoboolean
namestring
autocompletestring
acceptcharsetstring
actionstring
enctypestring
methodstring
novalidatefalse | true | "true" | "false"
targetstring
ui{ root?: SlotClass; header?: SlotClass; leading?: SlotClass; leadingIcon?: SlotClass; title?: SlotClass; description?: SlotClass; body?: SlotClass; providers?: SlotClass; checkbox?: SlotClass; select?: SlotClass; password?: SlotClass; otp?: SlotClass; input?: SlotClass; separator?: SlotClass; form?: SlotClass; footer?: SlotClass; }
此组件还支持所有原生的 <form> HTML 属性。

插槽

插槽类型
页头{}
前置{ ui: object; }
title{}
description{}
providers{}
separator{}
validation{}
submit{ loading: boolean; }
页脚{}

事件

事件类型
submit[payload: FormSubmitEvent<Reactive<InferInput<T>>>]

可访问属性

您可以使用 useTemplateRef 访问类型化组件实例(暴露 formRef 和 state)。例如,在单独的表单(如“重置”表单)中,您可以执行以下操作:

<script setup lang="ts">
const authForm = useTemplateRef('authForm')
</script>

<template>
  <UAuthForm ref="authForm" />
</template>

这使您可以访问以下(暴露的)属性:

名称类型
formRefRef<HTMLFormElement | null>
stateReactive<FormStateType>

主题

app.config.ts
export default defineAppConfig({
  ui: {
    authForm: {
      slots: {
        root: 'w-full space-y-6',
        header: 'flex flex-col text-center',
        leading: 'mb-2',
        leadingIcon: 'size-8 shrink-0 inline-block',
        title: 'text-xl text-pretty font-semibold text-highlighted',
        description: 'mt-1 text-base text-pretty text-muted',
        body: 'gap-y-6 flex flex-col',
        providers: 'space-y-3',
        checkbox: '',
        select: 'w-full',
        password: 'w-full',
        otp: 'w-full',
        input: 'w-full',
        separator: '',
        form: 'space-y-5',
        footer: 'text-sm text-center 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({
      ui: {
        authForm: {
          slots: {
            root: 'w-full space-y-6',
            header: 'flex flex-col text-center',
            leading: 'mb-2',
            leadingIcon: 'size-8 shrink-0 inline-block',
            title: 'text-xl text-pretty font-semibold text-highlighted',
            description: 'mt-1 text-base text-pretty text-muted',
            body: 'gap-y-6 flex flex-col',
            providers: 'space-y-3',
            checkbox: '',
            select: 'w-full',
            password: 'w-full',
            otp: 'w-full',
            input: 'w-full',
            separator: '',
            form: 'space-y-5',
            footer: 'text-sm text-center text-muted mt-2'
          }
        }
      }
    })
  ]
})

更新日志

暂无近期更新