Authentique

Un formulaire personnalisable pour créer des formulaires de login, d

Utilisation

Construit sur le composant Form, le composant AuthForm peut être utilisé dans vos pages ou enveloppé dans un PageCard.

Login
Enter your credentials to access your account.
<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>

champs

Le formulaire se construira lui-même sur la base de la prop fields et l'état sera géré en interne.

Utilisez le prop fields comme tableau d'objets avec les propriétés suivantes:

  • xname: stringxx{lang="ts-type"}
  • xtype: 'checkbox' | 'select' | 'otp' | 'InputHTMLAttributes['type']'x{lang="ts-type"}

Chaque champ doit inclure une propriété type, qui détermine le composant d'entrée et tout accessoire supplémentaire appliqué: Les champs checkbox utilisent les props Checkbox, les champs select utilisent les props SelectMenu, les champs otp utilisent les props PinInput, et tous les autres types utilisent des accessoires Input.

Vous pouvez également passer n'importe quelle propriété du composant FormField à chaque champ.

You will be logged in for 30 days.

<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>

Titre

Utilisez la prop title pour définir le titre du formulaire.

Login
<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>

Définition

Utilisez la prop description pour définir la description du formulaire.

Login
Enter your credentials to access your account.
<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>

Icône

Utilisez la prop icon pour définir l'icône du formulaire.

Login
Enter your credentials to access your account.
<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>

Fournisseur

Utilisez la prop providers pour ajouter des fournisseurs au formulaire.

Vous pouvez passer n'importe quelle propriété du composant Button telle que variant, color, to, etc.

Login
Enter your credentials to access your account.
<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>

Séparateur

Utilisez la prop separator pour personnaliser le Separator entre les fournisseurs et les champs.

Login
Enter your credentials to access your account.
<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>

Vous pouvez passer n'importe quelle propriété du composant Separator pour le personnaliser.

Login
Enter your credentials to access your account.
<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>

Soumettre

Utilisez la prop submit pour modifier le bouton d'envoi du formulaire.

Vous pouvez passer n'importe quelle propriété du composant Button telle que variant, color, to, etc.

Login
Enter your credentials to access your account.
<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>

Exemples

Dans une page

Vous pouvez envelopper le composant AuthForm avec le composant PageCard pour l'afficher dans une page login.vue par exemple.

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, 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 équipement

Props

Prop Default Type
as
'div'
any

The element or component this component should render as.

icon
any

The icon displayed above the title.

title
string
description
string
fields
F[]
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
Omit<ButtonProps, LinkPropsKeys>

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

schema
T
validate
(state: Partial<InferInput<T>>): FormError<string>[] | Promise<FormError<string>[]>
validateOn
FormInputEvents[]
validateOnInputDelay
number
disabled
boolean
loading
boolean
loadingAuto
boolean
name
string
autocomplete
string
acceptcharset
string
action
string
enctype
string
method
string
novalidate
false | true | "true" | "false"
target
string
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; }
Ce composant prend également en charge tous les attributs HTML natifs <form>.

Slots

Slot Type
header
{}
leading
{ ui: object; }
title
{}
description
{}
providers
{}
separator
{}
validation
{}
submit
{ loading: boolean; }
footer
{}

Emits

Event Type
submit
[payload: FormSubmitEvent<InferOutput<T>>]

Expose à

Vous pouvez accéder à l'instance du composant typé (exposant formRef et state) en utilisant useTemplateRef. Par exemple, dans un formulaire séparé (par exemple un formulaire "reset"), vous pouvez faire:

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

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

Cela vous donne accès aux propriétés (exposées) suivantes:

nomtype
formRefx{lang="ts-type"}Ref<HTMLFormElement | null>x{lang="ts-type"}
statex{lang="ts-type"}Reactive<FormStateType>x{lang="ts-type"}

Thème

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'
          }
        }
      }
    })
  ]
})

Changelog écrit

No recent changes