Form Controls
SvSeeds provides form controls as Field components such as TextField. All Field components share a unified structure and validation functionality.
Basic Structure
All Field components are composed of the following structured parts:
whole (div) - Overall wrapper
├─ top - Wrapper for label elements
│ ├─ label - Label text
│ ├─ extra - Label supplement (e.g., "optional")
│ └─ aux - Additional information (e.g., character counter)
├─ middle - Input element wrapper
│ └─ main - Input element (Only CheckField has a different structure)
└─ bottom - Field description and error messagesDesign Rationale
We use a div element for the whole container. We avoid using fieldset elements because they render an anonymous fieldset content box, which complicates styling.
Validation Features
Field components provide built-in validation functionality.
Validation Function Type Definitions
TypeScript type definitions are provided for each Field component. Please refer to the individual component documentation for details.
Validation Patterns
Field components support three validation patterns:
1. Using Custom Functions
Validation runs immediately after user input. No validation occurs when the field value(s) is empty.
<script lang="ts">
import { TextField, type TextFieldValidation } from "svseeds";
const validations: TextFieldValidation[] = [
(value: string) => [...value].length > 10 ? "Please enter 10 characters or less" : "",
(value: string) => !value ? "This field is required" : "",
];
</script>
<TextField {validations} />2. Using Attributes + Custom Functions
You can combine validation attributes with custom error messages.
<script lang="ts">
import type { HTMLInputAttributes } from "svelte/elements";
import { TextField, type TextFieldValidation } from "svseeds";
const validations: TextFieldValidation[] = [
(value: string, validity: ValidityState) => {
if (validity.tooLong) return "Please enter 10 characters or less";
if (validity.valueMissing) return "This field is required";
}
];
const attributes: HTMLInputAttributes = {
maxlength: 10,
required: true,
};
</script>
<TextField {validations} {attributes} />3. Browser Native Validation
Standard browser validation messages are displayed during form submission.
<script lang="ts">
import type { HTMLInputAttributes } from "svelte/elements";
import { TextField } from "svseeds";
const attributes: HTMLInputAttributes = {
maxlength: 10,
required: true,
};
</script>
<TextField {attributes} />Variant Transitions
The variant prop automatically transitions based on input state:
neutral- Initial state or empty stateinactive- Validation failed stateactive- Validation passed state
Form-wide Validation
Basic Pattern
When validating multiple Field components simultaneously, use a form element:
<script lang="ts">
import { TextField } from "svseeds";
let form = $state();
const validations = [
(value: string) => !value ? "This field is required" : "",
];
const onclick = () => form?.checkValidity();
</script>
<form bind:this={form}>
<TextField {validations} />
<TextField {validations} />
<button type="button" {onclick}>Validate</button>
</form>Integration with Button Component
Using SvSeeds’ Button component allows for more concise code. When onclick is set on a Button, it only runs if form?.checkValidity() returns true.
<script lang="ts">
import { Button, TextField } from "svseeds";
let form = $state();
const validations = [
(value: string) => !value ? "Input is required" : "",
];
const onclick = () => console.log("OK");
</script>
<form bind:this={form}>
<TextField {validations} />
<TextField {validations} />
<Button bind:form {onclick}>Validate</Button>
</form>Form Submission
To submit form data, set the name attribute using the attributes prop:
<script lang="ts">
import { Button, TextField } from "svseeds";
let form = $state();
</script>
<form bind:this={form} method="post" action="/submit">
<TextField attributes={{ name: "username" }} />
<TextField attributes={{ name: "email" }} />
<Button type="submit" bind:form>Submit</Button>
</form>