- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Menubar
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- Typography
Installation#
pnpm dlx shadcn@latest add @force-ui-svelte/form
Usage#
Create a form schema#
Define the shape of your form using a Zod schema. You can read more about using Zod in the Zod documentation. We're going to define it in a file called schema.ts in the same directory as our page component, but you can put it anywhere you like.
import { z } from "zod"
export const formSchema = z.object({
username: z.string().min(2).max(50),
})
export type FormSchema = typeof formSchemaSetup the load function#
import { superValidate } from "sveltekit-superforms"
import { zod4 } from "sveltekit-superforms/adapters"
import type { PageServerLoad } from "./$types.js"
import { formSchema } from "./schema"
export const load: PageServerLoad = async () => {
return {
form: await superValidate(zod4(formSchema)),
}
}Create form component#
For this example, we'll be passing the form returned from the load function as a prop to this component. To ensure it's typed properly, we'll use the SuperValidated type from sveltekit-superforms, and pass in the type of our form schema.
<script lang="ts">
import * as Form from "$lib/components/ui/form/index.js";
import { Input } from "$lib/components/ui/input/index.js";
import { formSchema, type FormSchema } from "./schema";
import {
type SuperValidated,
type Infer,
superForm,
} from "sveltekit-superforms";
import { zod4Client } from "sveltekit-superforms/adapters";
let { data }: { data: { form: SuperValidated<Infer<FormSchema>> } } =
$props();
const form = superForm(data.form, {
validators: zod4Client(formSchema),
});
const { form: formData, enhance } = form;
</script>
<form method="POST" use:enhance>
<Form.Field {form} name="username">
<Form.Control>
</Form.Control>
<Form.Description>This is your public display name.</Form.Description>
<Form.FieldErrors />
</Form.Field>
<Form.Button>Submit</Form.Button>
</form>The name, id, and all accessibility attributes are applied to the input by spreading the attrs object from the Form.Control component. The Form.Label will automatically be associated with the input using the for attribute, so you don't have to worry about that.
Use the component#
We'll pass the form from the data returned from the load function to the form component we created above.
<script lang="ts">
import type { PageData } from "./$types.js";
import SettingsForm from "./settings-form.svelte";
let { data }: { data: PageData } = $props();
</script>
<SettingsForm {data} />Create an Action#
import { fail } from "@sveltejs/kit"
import { superValidate } from "sveltekit-superforms"
import { zod4 } from "sveltekit-superforms/adapters"
import type { Actions, PageServerLoad } from "./$types.js"
import { formSchema } from "./schema"
export const load: PageServerLoad = async () => {
return {
form: await superValidate(zod4(formSchema)),
}
}
export const actions: Actions = {
default: async (event) => {
const form = await superValidate(event, zod4(formSchema))
if (!form.valid) {
return fail(400, {
form,
})
}
return {
form,
}
},
}Done#
That's it. You now have a fully accessible form that is type-safe and has client & server side validation.
Next Steps#
Be sure to check out the Formsnap and Superforms documentation for more information on how to use them.
Examples#
See the following links for more examples on how to use the other Form components: