Menu

Change language

GitHub repo

Form

formui

Zod-first form block built on TanStack Svelte Form. Wires field labels, descriptions, error messages, and validation together; bind a field once and the rest is automatic.

Installation

$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/form.json
Manifest:https://uipkge.dev/r/svelte/form.jsonInstalls to:src/lib/components/ui/form/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
form

React is intentional: React's `Form` is a react-hook-form `FormProvider` (no DOM, methods spread by the consumer), while Svelte renders the `<form>` itself and takes the instance as a prop.

TanstackFormApi—required
refHTMLFormElement | null—optional

Schema

Type aliases from this item's source — use them to shape the data you pass in.

FormFieldContext
interface FormFieldContext {
  name: string
  error: () => string | undefined
  valid: () => boolean
  isDirty: () => boolean
  isTouched: () => boolean
}
TanstackFormApi
interface TanstackFormApi {
  Field: Component<any>
  handleSubmit: () => void | Promise<void>
}

Files installed (15)

  • src/lib/components/ui/form/Form.svelte1.3 kB
    <script lang="ts" module>
      import type { HTMLFormAttributes } from 'svelte/elements'
      import type { TanstackFormApi } from './context'
    
      export interface FormProps extends HTMLFormAttributes {
        /** TanStack form instance from `createForm`. Structural divergence from
         *  React is intentional: React's `Form` is a react-hook-form
         *  `FormProvider` (no DOM, methods spread by the consumer), while Svelte
         *  renders the `<form>` itself and takes the instance as a prop. */
        form: TanstackFormApi
        ref?: HTMLFormElement | null
      }
    </script>
    
    <script lang="ts">
      import { setContext, untrack } from 'svelte'
      import { cn } from '$lib/utils'
      import { FORM_INSTANCE_CONTEXT_KEY } from './context'
    
      let { class: className, form, children, ref = $bindable(null), ...restProps }: FormProps = $props()
    
      // `untrack` — the form object identity is stable for the component's
      // lifetime (created once by `createForm`), so initial capture is correct.
      setContext(FORM_INSTANCE_CONTEXT_KEY, untrack(() => form))
    
      function onSubmit(e: SubmitEvent) {
        e.preventDefault()
        e.stopPropagation()
        void form.handleSubmit()
      }
    </script>
    
    <form bind:this={ref} data-uipkge data-slot="form" class={cn(className)} onsubmit={onSubmit} {...restProps}>
      {@render children?.()}
    </form>
    
  • src/lib/components/ui/form/FormActions.svelte0.9 kB
  • src/lib/components/ui/form/FormControl.svelte1.2 kB
  • src/lib/components/ui/form/FormDescription.svelte0.7 kB
  • src/lib/components/ui/form/FormField.svelte1.1 kB
  • src/lib/components/ui/form/FormFieldInner.svelte3.2 kB
  • src/lib/components/ui/form/FormItem.svelte3.2 kB
  • src/lib/components/ui/form/FormLabel.svelte0.7 kB
  • src/lib/components/ui/form/FormMessage.svelte0.7 kB
  • src/lib/components/ui/form/FormSection.svelte1.3 kB
  • src/lib/components/ui/form/FormStatus.svelte1.5 kB
  • src/lib/components/ui/form/index.ts1.3 kB
  • src/lib/components/ui/form/context.ts0.5 kB
  • src/lib/components/ui/form/types.ts0.1 kB
  • src/lib/components/ui/form/useFormField.ts1.1 kB

Raw manifest:https://uipkge.dev/r/svelte/form.json