All skills
onmax avatar

/nuxt-ui

@de09c7b official
by Maxonmax/nuxt-skills715 stars
38

Build UIs with @nuxt/ui v4 — 125+ accessible Vue components with Tailwind CSS theming. Use when creating interfaces, customizing themes to match a brand, building forms, or composing layouts like dashboards, docs sites, and chat interfaces.

Use this Skill: https://skilld.dev/gh/onmax/nuxt-skills/nuxt-ui

This session only. Nothing lands on disk.

referencesguidelinesforms.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Forms

Basic pattern

Nuxt UI forms use UForm + UFormField + Standard Schema validation (Zod, Valibot, Yup, or Joi).

<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'

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

type Schema = z.output<typeof schema>
const state = reactive<Partial<Schema>>({ email: '', password: '' })

function onSubmit(event: FormSubmitEvent<Schema>) {
  // UForm validates before emitting @submit — access validated data via event.data
}
</script>

<template>
  <UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
    <UFormField name="email" label="Email" required>
      <UInput v-model="state.email" type="email" placeholder="you@example.com" />
    </UFormField>

    <UFormField name="password" label="Password" required>
      <UInput v-model="state.password" type="password" placeholder="Min 8 characters" />
    </UFormField>

    <UButton type="submit" label="Sign in" />
  </UForm>
</template>

Key rules

  • Always use UFormField around inputs — it connects validation errors via the name prop
  • The name prop on UFormField must match the schema field name exactly
  • Use reactive<Partial<Schema>>({}) for state — Partial allows empty initial values
  • @submit only fires when validation passes
  • For nested objects, use dot notation: name="address.city"

UFormField props

Prop Purpose
name Links to schema field for validation errors
label Visible label text
description Help text below the input
hint Right-aligned hint text (e.g., "Optional")
required Shows required indicator
size Inherits to child input

Field layout patterns

Vertical stack (default)

<UForm :schema="schema" :state="state" class="space-y-4">
  <UFormField name="name" label="Name">
    <UInput v-model="state.name" />
  </UFormField>
  <UFormField name="email" label="Email">
    <UInput v-model="state.email" />
  </UFormField>
</UForm>

Inline fields with UFieldGroup

<UFieldGroup>
  <UFormField name="firstName" label="First name">
    <UInput v-model="state.firstName" />
  </UFormField>
  <UFormField name="lastName" label="Last name">
    <UInput v-model="state.lastName" />
  </UFormField>
</UFieldGroup>

Grid layout

<UForm :schema="schema" :state="state" class="grid grid-cols-2 gap-4">
  <UFormField name="firstName" label="First name">
    <UInput v-model="state.firstName" />
  </UFormField>
  <UFormField name="lastName" label="Last name">
    <UInput v-model="state.lastName" />
  </UFormField>
  <UFormField name="email" label="Email" class="col-span-2">
    <UInput v-model="state.email" type="email" />
  </UFormField>
</UForm>

Common field patterns

Select

<UFormField name="role" label="Role">
  <USelect v-model="state.role" :items="['Admin', 'Editor', 'Viewer']" placeholder="Choose role" />
</UFormField>

Checkbox

<UFormField name="terms">
  <UCheckbox v-model="state.terms" label="I agree to the terms and conditions" />
</UFormField>

Radio group

<UFormField name="plan" label="Plan">
  <URadioGroup
    v-model="state.plan"
    :items="[
      { label: 'Free', value: 'free', description: 'For personal projects' },
      { label: 'Pro', value: 'pro', description: 'For teams' }
    ]"
  />
</UFormField>

Switch

<UFormField name="notifications" label="Email notifications">
  <USwitch v-model="state.notifications" />
</UFormField>

Textarea

<UFormField name="bio" label="Bio" description="Brief description for your profile.">
  <UTextarea v-model="state.bio" :rows="3" autoresize :maxrows="6" />
</UFormField>

File upload

<UFormField name="avatar" label="Avatar">
  <UFileUpload v-model="state.avatar" accept="image/*" />
</UFormField>

<!-- Or as a drop area -->
<UFormField name="documents" label="Documents">
  <UFileUpload v-model="state.documents" multiple variant="area" />
</UFormField>

Date

<UFormField name="date" label="Date">
  <UInputDate v-model="state.date" />
</UFormField>

<!-- Date range -->
<UFormField name="dateRange" label="Date range">
  <UInputDate v-model="state.dateRange" range />
</UFormField>

Programmatic validation

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

async function validateAndSubmit() {
  const result = await form.value?.validate({ silent: true })
  if (result) {
    // valid — submit
  }
}

async function validateEmail() {
  await form.value?.validate({ name: 'email', silent: true })
}

function setServerError() {
  form.value?.setErrors([
    { name: 'email', message: 'Email already taken' }
  ])
}

function resetErrors() {
  form.value?.clear()
}
</script>

<template>
  <UForm ref="form" :schema="schema" :state="state" @submit="onSubmit">
    <!-- fields -->
  </UForm>
</template>

By default, validate() throws a FormValidationException when validation fails. Pass { silent: true } when you want it to return false instead. Use clear() to remove validation errors.

Form in a modal

Use #footer="{ close }" scoped slot for cancel/submit actions. Wrap the modal body in UForm with a type="submit" button in the footer so validation runs on submit.

<UModal v-model:open="isOpen" title="Edit profile" description="Update your information." :ui="{ footer: 'justify-end' }">
  <template #body>
    <UForm id="profile-form" :schema="schema" :state="state" class="space-y-4" @submit="onSave">
      <UFormField name="name" label="Name">
        <UInput v-model="state.name" />
      </UFormField>
      <UFormField name="email" label="Email">
        <UInput v-model="state.email" type="email" />
      </UFormField>
    </UForm>
  </template>
  <template #footer="{ close }">
    <UButton label="Cancel" color="neutral" variant="outline" @click="close" />
    <UButton type="submit" form="profile-form" label="Save" />
  </template>
</UModal>

Source: SKILL.md on GitHub

No alerts12d5 checks · Risk SAFE
  • Gen Agent Trust Hub12d

    The skill provides comprehensive documentation and implementation guidance for the Nuxt UI v4 component library. It includes a maintenance script for synchronizing documentation with the official repository. No malicious patterns or security risks were identified.

  • Socket12d

    No alerts

  • Snyk12d

    Risk: LOW · No issues

  • Runlayer7mo

    129 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at de09c7b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated last week

README badge

README badge for onmax/nuxt-skills/nuxt-ui

Builds styled UI for Nuxt 4+ using @nuxt/ui v4 components with Tailwind CSS and Tailwind Variants. Covers forms with validation, data tables, modals, and theme customization through semantic colors and CSS variables.

Generated from the current SKILL.md.

Does this skill cover Reka UI headless primitives?
No. This skill focuses on @nuxt/ui v4 components (styled, opinionated). For Reka UI primitives, accessibility patterns, and asChild behavior, use the reka-ui skill instead.
What form validation libraries does this support?
Zod and Valibot. The skill includes guidance on useFormField and form component integration with both libraries.
Do I need UApp wrapper?
Yes, UApp is required to use Toast, Tooltip, and overlay components like Modal and Slideover.
Can I customize colors and theme?
Yes. The skill covers semantic colors, CSS variables, app.config.ts setup, and Tailwind Variants for type-safe styling.
What Nuxt and Vue versions does this require?
Vue 3 and Nuxt 4+. The current stable version is v4.4.0 (January 2026).

Generated from the current SKILL.md. These answers refresh after source changes.