Form

Typed form scaffolding on formsnap + sveltekit-superforms. Label, Control, Description, and FieldErrors compose around a bloom control while the form owns validation and accessibility wiring.

Usage

Form is a thin wrapper over formsnap and sveltekit-superforms. Feed it a superforms instance from a SvelteKit +page.svelte load and render fields with typed name paths. Errors and aria wiring come for free.

Form requires a live superForm instance from a SvelteKit route. See the Code tab for a minimal end-to-end example.

Form.Field props

Thin wrapper over formsnap's Field. name is typed against the form schema via generics.

PropTypeDescription
SuperForm<T>The superforms instance returned by superForm(data.form).
FormPath<T>Typed field path. Intellisense is derived from the form schema passed to superForm.
stringMerged onto the wrapper via tailwind-merge.

Form.Control usage

Form.Control exposes a child snippet with props that wire the associated control to the label and error region.

PropTypeDescription
Snippet<{ props: Record<string, unknown> }>Render the control inside and spread props onto it.

Form.FieldErrors props

Renders scoped error messages for the enclosing field. Variables bind straight from formsnap context.

PropTypeDescription
string | null | undefinedOptional class applied to each error row when the default renderer is used.
Snippet<{ errors: string[]; errorProps: Record<string, unknown> }>Custom rendering. Override when you need icons, links, or non-standard layout.
stringMerged onto the container via tailwind-merge.
<script lang="ts" generics="T extends Record<string, unknown>, U extends FormPath<T>">
	import * as FormPrimitive from 'formsnap';
	import type { FormPath } from 'sveltekit-superforms';
	import { cn, type WithElementRef, type WithoutChildren } from '$lib/utils.js';
	import type { HTMLAttributes } from 'svelte/elements';

	let {
		ref = $bindable(null),
		class: className,
		form,
		name,
		children: childrenProp,
		...restProps
	}: FormPrimitive.FieldProps<T, U> &
		WithoutChildren<WithElementRef<HTMLAttributes<HTMLDivElement>>> = $props();
</script>

<FormPrimitive.Field {form} {name}>
	{#snippet children({ constraints, errors, tainted, value })}
		<div bind:this={ref} data-slot="form-item" class={cn('space-y-2', className)} {...restProps}>
			{@render childrenProp?.({ constraints, errors, tainted, value: value as T[U] })}
		</div>
	{/snippet}
</FormPrimitive.Field>