Skip to content

Functional, accessible, and powerful form components for Svelte. 🫰

License

Notifications You must be signed in to change notification settings

svecosystem/formsnap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

232 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Formsnap

npm version npm downloads license

The goal of this library is to make working with the already incredible sveltekit-superforms even more pleasant, by wrapping it with accessible form components.

Installation

npm i formsnap sveltekit-superforms <your-schema-library>

Usage

You'll handle the initial Superforms setup just as you normally would, where you define a schema and return the form from your load function.

1. Define a Zod schema

// schemas.ts
import { z } from "zod";
export const settingsFormSchema = z.object({
	email: z.string().email(),
	bio: z.string().max(250).optional(),
	marketingEmails: z.boolean().default(true),
	language: z.enum(["en", "es", "fr"]).default("en"),
	theme: z.enum(["light", "dark"]).default("light"),
});

2. Return the form from your load function

// +page.server.ts
import { superValidate } from "sveltekit-superforms";
import { zod } from "sveltekit-superforms/adapters";
import type { PageServerLoad } from "./$types";
import { settingsFormSchema } from "./schemas";

export const load: PageServerLoad = async () => {
	return {
		form: await superValidate(zod(settingsFormSchema)),
	};
};

3. Construct the form in your page

<script lang="ts">
	import { Field, Label, FieldErrors, Control, Description, Fieldset, Legend } from "formsnap";
	import { settingsFormSchema } from "./schemas";
	import { superForm } from "sveltekit-superforms";
	import { zodClient } from "sveltekit-superforms/adapters";

	let { data } = $props();

	const form = superForm(data.form, {
		validators: zodClient(settingsFormSchema),
	});

	const { form: formData, enhance } = form;
</script>

<form method="POST" use:enhance>
	<Field {form} name="email">
		<Control>
			{#snippet children({ props })}
				<Label>Email</Label>
				<input type="email" {...props} bind:value={$formData.email} />
			{/snippet}
		</Control>
		<Description>We'll provide critical updates about your account via email.</Description>
		<FieldErrors />
	</Field>

	<Field {form} name="bio">
		<Control>
			{#snippet children({ props })}
				<Label>Bio</Label>
				<textarea bind:value={$formData.bio} {...props} />
			{/snippet}
		</Control>
		<FieldErrors />
	</Field>

	<Field {form} name="language">
		<Control>
			{#snippet children({ props })}
				<Label>Language</Label>
				<select {...props} bind:value={$formData.language}>
					<option value="en">English</option>
					<option value="es">Spanish</option>
					<option value="fr">French</option>
				</select>
			{/snippet}
		</Control>
		<FieldErrors />
	</Field>

	<Field {form} name="marketingEmails">
		<Control>
			{#snippet children({ props })}
				<Label>Receive marketing emails from us</Label>
				<input type="checkbox" {...props} bind:checked={$formData.marketingEmails} />
			{/snippet}
		</Control>
		<FieldErrors />
	</Field>

	<Fieldset {form} name="theme">
		<Legend>Select your theme</Legend>
		{#each ["light", "dark"] as theme}
			<Control>
				{#snippet children({ props })}
					<input {...props} type="radio" bind:group={$formData.theme} value={theme} />
					<Label>{theme}</Label>
				{/snippet}
			</Control>
		{/each}
		<FieldErrors />
	</Fieldset>

	<button type="submit">Submit</button>
</form>

Check out Formsnap.dev for more documentation.

Sponsors

This project is supported by the following beautiful people/organizations:

Logos from Sponsors

License

Published under the MIT license. Made by @huntabyte and community 💛

Community

Join the Discord server to ask questions, find collaborators, or just say hi!

Svecosystem Discord community