Forms
newt/ui ships form controls, not a form library. Pick the one you already use and wire it to them.
form-fields is presentational on purpose: Field, Label, Input,
Textarea, Select, Switch, Checkbox and FieldHelp, styled like the
client’s settings panels and reading the same tokens as everything else. There
is no <Form> wrapper, no resolver and no schema of its own.
That is a deliberate omission. Form state, validation and submission are a solved problem with three good answers, and a fourth wrapper around one of them is a dependency you would have to unpick the first time you needed something it did not do.
newt-fieldimport {
Field,
FieldHelp,
Input,
Label,
Switch,
} from "@/registry/bases/newt/ui/form-fields"
export default function FormFieldsDemo() {
return (
<div className="flex w-full max-w-sm flex-col gap-6">
<Field>
<Label htmlFor="newt-input-example">Label</Label>
<Input id="newt-input-example" placeholder="Placeholder" />
<FieldHelp>Helper text</FieldHelp>
</Field>
<div className="flex items-center justify-between text-newt-text-primary">
<span>Toggle label</span>
<Switch aria-label="Toggle label" />
</div>
</div>
)
}<script setup lang="ts">
import { ref } from "vue"
import {
Field,
FieldHelp,
Input,
Label,
Switch,
} from "~~/registry/bases/newt/ui/form-fields"
const value = ref("")
const enabled = ref(false)
</script>
<template>
<div class="flex w-full max-w-sm flex-col gap-6">
<Field>
<Label for="newt-input-example">Label</Label>
<Input
id="newt-input-example"
v-model="value"
placeholder="Placeholder"
/>
<FieldHelp>Helper text</FieldHelp>
</Field>
<div class="flex items-center justify-between text-newt-text-primary">
<span>Toggle label</span>
<Switch v-model="enabled" aria-label="Toggle label" />
</div>
</div>
</template>What the components give you
A validation state that is set once. Field takes invalid; the controls
inside read it from the wrapper, so a library that only knows “this field
failed” says it in one place:
<Field invalid={Boolean(errors.name)}>
<Label>Channel name</Label>
<Input aria-invalid={Boolean(errors.name)} />
{errors.name && <FieldHelp variant="error">{errors.name}</FieldHelp>}
</Field>
An error that is announced. FieldHelp variant="error" carries
role="alert", so a message that appears after a failed submit reaches a
reader who is not looking at that part of the page.
Pick a library
| Library | Frameworks | Guide |
|---|---|---|
| react-hook-form | React | Guide |
| TanStack Form | React + Vue | Guide |
| vee-validate | Vue | Guide |
All three examples validate with zod and build the same form — creating a channel — so they can be read side by side.