Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Guidance for building UIs with Nuxt UI, the official Tailwind-based component library for Nuxt.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/recipes/auth.md
1# Auth Forms23## UAuthForm (recommended)45`UAuthForm` provides a complete auth form with fields, providers, validation, and submit — no manual `UForm` + `UFormField` wiring needed. Wrap it in `UPageCard` for a polished look.67```vue [pages/login.vue]8<script setup lang="ts">9import * as z from 'zod'10import type { FormSubmitEvent, AuthFormField } from '@nuxt/ui'1112const fields: AuthFormField[] = [{13name: 'email',14type: 'email',15label: 'Email',16placeholder: 'Enter your email',17required: true18}, {19name: 'password',20label: 'Password',21type: 'password',22placeholder: 'Enter your password',23required: true24}, {25name: 'remember',26label: 'Remember me',27type: 'checkbox'28}]2930const providers = [{31label: 'Google',32icon: 'i-simple-icons-google',33onClick: () => navigateTo('/auth/google', { external: true })34}, {35label: 'GitHub',36icon: 'i-simple-icons-github',37onClick: () => navigateTo('/auth/github', { external: true })38}]3940const schema = z.object({41email: z.email('Invalid email'),42password: z.string('Password is required').min(8, 'Must be at least 8 characters')43})4445type Schema = z.output<typeof schema>4647function onSubmit(payload: FormSubmitEvent<Schema>) {48// payload.data contains validated fields49}50</script>5152<template>53<div class="flex min-h-dvh items-center justify-center">54<UPageCard class="w-full max-w-md">55<UAuthForm56:schema="schema"57:fields="fields"58:providers="providers"59title="Welcome back!"60description="Sign in to your account."61icon="i-lucide-lock"62@submit="onSubmit"63>64<template #password-hint>65<ULink to="/forgot-password" class="text-primary font-medium">Forgot password?</ULink>66</template>67<template #footer>68Don't have an account? <ULink to="/signup" class="text-primary font-medium">Sign up</ULink>.69</template>70</UAuthForm>71</UPageCard>72</div>73</template>74```7576### UAuthForm key props7778| Prop | Purpose |79|---|---|80| `title`, `description`, `icon` | Header content |81| `fields` | `AuthFormField[]` — each has `name`, `type`, `label`, `placeholder`, `required` |82| `providers` | `ButtonProps[]` — social login buttons shown above/below the form |83| `schema` | Zod/Valibot schema for validation |84| `submit` | Customize submit button: `{ label: 'Sign in', block: true }` |85| `separator` | Text between providers and fields (default: `'or'`) |8687### UAuthForm key slots8889| Slot | Purpose |90|---|---|91| `#description` | Override description (e.g., add sign-up link) |92| `#password-hint` | "Forgot password?" link on password field |93| `#validation` | Custom error display (e.g., `UAlert`) |94| `#footer` | Terms of service, sign-up link |95| `#<field>-field` | Override a specific field's rendering |9697## Custom auth layout9899For layouts where `UAuthForm` is too opinionated, use `UCard` + `UForm` + `UFormField` directly.100101```vue [pages/login.vue]102<script setup lang="ts">103import * as z from 'zod'104import type { FormSubmitEvent } from '@nuxt/ui'105106const schema = z.object({107email: z.email('Invalid email'),108password: z.string().min(1, 'Password is required')109})110111type Schema = z.output<typeof schema>112const state = reactive<Partial<Schema>>({ email: '', password: '' })113114async function onSubmit(event: FormSubmitEvent<Schema>) {115// event.data contains validated fields116}117</script>118119<template>120<div class="flex min-h-dvh items-center justify-center">121<UCard class="w-full max-w-sm">122<template #header>123<div class="text-center">124<h1 class="text-xl font-semibold text-default">Welcome back</h1>125<p class="mt-1 text-sm text-muted">Sign in to your account</p>126</div>127</template>128129<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">130<UFormField name="email" label="Email">131<UInput v-model="state.email" type="email" placeholder="[email protected]" />132</UFormField>133134<UFormField name="password" label="Password">135<template #hint>136<NuxtLink to="/forgot-password" class="text-sm text-primary">Forgot password?</NuxtLink>137</template>138<UInput v-model="state.password" type="password" />139</UFormField>140141<UButton type="submit" label="Sign in" block />142</UForm>143144<template #footer>145<p class="text-center text-sm text-muted">146Don't have an account?147<NuxtLink to="/signup" class="text-primary font-medium">Sign up</NuxtLink>148</p>149</template>150</UCard>151</div>152</template>153```154155## Tips156157- Prefer `UAuthForm` with `UPageCard` for standard auth pages — handles layout, providers, validation, and submit158- Use `import * as z from 'zod'` and `z.email()` (Zod 4 syntax)159- Type the submit handler: `function onSubmit(event: FormSubmitEvent<Schema>)` — access validated data via `event.data`160- Center auth forms with `flex min-h-dvh items-center justify-center`161- Place "Forgot password?" link as `#password-hint` slot on `UAuthForm`, or `#hint` slot on `UFormField`162- Social login buttons: use `providers` prop on `UAuthForm`, or add manually with `<USeparator label="or" />`163