# Nuxt UI FormKit
> FormKit integration for Nuxt UI - Seamlessly connect FormKit form handling with Nuxt UI components
---
# Installation
Get started with Nuxt UI FormKit by installing the module in your Nuxt application.
## Prerequisites
Before you begin, make sure you have the following installed:
- **Node.js** - a version supported by Nuxt 4
- **Nuxt** 4.x
- **pnpm**, **npm**, or **yarn** package manager
## Install Package
Install the `@sfxcode/nuxt-ui-formkit` module using your preferred package manager:
::: code-group
```bash [pnpm]
pnpm add @sfxcode/nuxt-ui-formkit
```
```bash [npm]
npm install @sfxcode/nuxt-ui-formkit
```
```bash [yarn]
yarn add @sfxcode/nuxt-ui-formkit
```
:::
## Module Configuration
Add the module to your `nuxt.config.ts`:
```typescript [nuxt.config.ts]
export default defineNuxtConfig({
modules: [
'@nuxt/ui',
'@formkit/nuxt',
'@sfxcode/nuxt-ui-formkit'
]
})
```
::: info
**Note:** Make sure to add `@nuxt/ui` before `@sfxcode/nuxt-ui-formkit` in the modules array.
:::
::: warning `@formkit/nuxt` is required in `modules`
This module does not register `@formkit/nuxt` for you. It ships as a dependency, but it must be listed in `modules` so Nuxt picks up your `formkit.config.ts` (below). Without it the `nuxtUI*` input types are never registered.
:::
## FormKit Configuration
Create a `formkit.config.ts` file in your project root to configure FormKit. The recommended way is `createNuxtUiFormkitConfig()`, which registers every `nuxtUIXxx` input/output (and its `form` name) plus this module's own plugins for you - spread its result into your own config alongside whatever else you need (locales, `iconLoader`, other plugins):
```typescript [formkit.config.ts]
import type { DefaultConfigOptions } from '@formkit/vue'
import { en } from '@formkit/i18n'
import { createAutoAnimatePlugin, createNuxtUiFormkitConfig } from '@sfxcode/nuxt-ui-formkit/formkit'
// `multiStep: true` additionally registers `createMultiStepPlugin()` -
// omit it if you're not using `nuxtUIMultiStep`/`nuxtUIStep`.
// Pass your own plugins through the `plugins` option: they are appended after
// this module's, so the asterisk plugin is kept.
const nuxtUiFormkitConfig = createNuxtUiFormkitConfig({
multiStep: true,
plugins: [
createAutoAnimatePlugin(
{
duration: 250,
easing: 'ease-in-out',
},
{
global: ['outer', 'inner'],
form: ['form'],
nuxtUIRepeater: ['input'],
}
),
],
})
const config: DefaultConfigOptions = {
locales: { en },
locale: 'en',
inputs: nuxtUiFormkitConfig.inputs,
plugins: nuxtUiFormkitConfig.plugins,
}
export default config
```
### The `form` prefix
Every input and output is also available under the library-neutral `form` prefix: `formInput` next to `nuxtUIInput`, `formSelect` next to `nuxtUISelect`, `formRepeater` next to `nuxtUIRepeater`, `formOutputText` next to `nuxtUIOutputText`, and so on. The `form` names are the same definitions, so both names behave identically. Use them when a schema should keep its type names across UI libraries that offer the same prefix, such as [FormKit PrimeVue](https://github.com/sfxcode/formkit-primevue).
`createNuxtUiFormkitConfig()` registers the `form` names next to the `nuxtUI` names, which are unchanged. If an input of your own happens to be called `formSelect` and must not be replaced, register only the `nuxtUI` names with `formPrefix: false`:
```typescript [formkit.config.ts]
const nuxtUiFormkitConfig = createNuxtUiFormkitConfig({ formPrefix: false })
```
```typescript
const schema = [
{ $formkit: 'formInput', name: 'name', label: 'Name', validation: 'required' },
{ $formkit: 'formSelect', name: 'role', label: 'Role', options: ['Tank', 'Healer'] },
]
```
The asterisk plugin, `createMultiStepPlugin`, the TypeScript types and the animation targets of `createAutoAnimatePlugin` treat the `form` names like the `nuxtUI` names: a target keyed `nuxtUIRepeater` also applies to `formRepeater`, and the other way round.
::: details Escape hatch: fully manual wiring
If you need finer-grained control (e.g. registering only a subset of inputs), you can still wire everything up yourself instead of using the helper:
```typescript [formkit.config.ts]
import type { DefaultConfigOptions } from '@formkit/vue'
import { en } from '@formkit/i18n'
import { nuxtUIInputs, nuxtUIOutputs } from '@sfxcode/nuxt-ui-formkit/definitions'
import { addNuxtAsteriskPlugin } from '@sfxcode/nuxt-ui-formkit/plugins'
const config: DefaultConfigOptions = {
locales: { en },
locale: 'en',
inputs: { ...nuxtUIInputs, ...nuxtUIOutputs },
plugins: [addNuxtAsteriskPlugin],
}
export default config
```
:::
## Verify Installation
Create a test page to verify the installation:
```vue [app.vue]
```
## Common Props
All output components support:
- `name` (required) - Field name in data object
- `label` - Display label
- `help` - Help text below value
- `color` - Component color
- `size` - Component size
### Icon Tooltips
Every `icon`/`leadingIcon`/`trailingIcon` pair described above also accepts a matching `*Tooltip` prop - `iconTooltip`, `leadingIconTooltip`, `trailingIconTooltip` (plus `trueIconTooltip`/`falseIconTooltip` on `nuxtUIOutputBoolean`, matching its `trueIcon`/`falseIcon`). Each accepts any Nuxt UI [`Tooltip`](https://ui.nuxt.com/components/tooltip) prop except `class` (e.g. `text`, `content`, `arrow`, `delayDuration`) as a plain object. No tooltip is rendered unless one is supplied.
```typescript
const schema = [
{
$formkit: 'nuxtUIOutputText',
name: 'userName',
label: 'Username',
leadingIcon: 'i-lucide-user',
leadingIconTooltip: { text: 'Unique account identifier' }
}
]
```
### Icon Accessibility
An icon with a click handler (`onIconClicked`, `onLeadingIconClicked`, `onTrailingIconClicked`) renders as a real `