Form
Form layout patterns with labels, inputs, validation states, and helper text.
Login Form
Standard vertical form layout with email and password fields.
<form class="vt-w-full vt-max-w-sm vt-space-y-4" onsubmit="event.preventDefault()">
<div class="vt-space-y-1.5">
<label class="vt-label vt-block" for="form-1-1">Email</label>
<div class="vt-relative">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-mail vt-absolute vt-left-3 vt-top-1/2 vt--translate-y-1/2 vt-w-4 vt-h-4 vt-text-foreground-muted">
<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>
</svg>
<input type="email" placeholder="you@example.com" class="vt-input vt-pl-10" id="form-1-1">
</div>
</div>
<div class="vt-space-y-1.5">
<label class="vt-label vt-block" for="form-1-2">Password</label>
<div class="vt-relative">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-lock vt-absolute vt-left-3 vt-top-1/2 vt--translate-y-1/2 vt-w-4 vt-h-4 vt-text-foreground-muted">
<rect width="18" height="11" x="3" y="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
<input type="password" placeholder="Enter password" class="vt-input vt-pl-10" id="form-1-2">
</div>
</div>
<button type="submit" class="vt-btn vt-btn-primary vt-w-full">Sign In</button>
</form>
With Helper Text
Form fields with hint text below the input.
Must be 3-20 characters, letters and numbers only
Maximum 160 characters
<div class="vt-w-full vt-max-w-sm vt-space-y-4">
<div class="vt-space-y-1.5">
<label class="vt-label vt-block" for="form-2-1">Username</label>
<div class="vt-relative">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-user vt-absolute vt-left-3 vt-top-1/2 vt--translate-y-1/2 vt-w-4 vt-h-4 vt-text-foreground-muted">
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle>
</svg>
<input type="text" placeholder="johndoe" class="vt-input vt-pl-10" id="form-2-1" aria-describedby="form-2-3">
</div>
<p class="vt-text-xs vt-text-foreground-muted" id="form-2-3">Must be 3-20 characters, letters and numbers only</p>
</div>
<div class="vt-space-y-1.5">
<label class="vt-label vt-block" for="form-2-2">Bio</label>
<textarea rows="3" placeholder="Tell us about yourself..." class="vt-textarea vt-resize-none" id="form-2-2" aria-describedby="form-2-4"></textarea>
<p class="vt-text-xs vt-text-foreground-muted" id="form-2-4">Maximum 160 characters</p>
</div>
</div>
Validation States
Error and success states with colored borders and messages.
Please enter a valid email address
Username is available
<div class="vt-w-full vt-max-w-sm vt-space-y-5">
<!-- Error state -->
<div class="vt-space-y-1.5">
<label class="vt-label vt-block" for="form-3-1">Email</label>
<input type="email" value="not-an-email" class="vt-input vt-input-error" id="form-3-1" aria-invalid="true" aria-describedby="form-3-3">
<p class="vt-text-xs vt-text-error-fill vt-flex vt-items-center vt-gap-1" id="form-3-3">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-circle-alert vt-w-3 vt-h-3">
<circle cx="12" cy="12" r="10"></circle><line x1="12" x2="12" y1="8" y2="12"></line><line x1="12" x2="12.01" y1="16" y2="16"></line>
</svg>
Please enter a valid email address
</p>
</div>
<!-- Success state -->
<div class="vt-space-y-1.5">
<label class="vt-label vt-block" for="form-3-2">Username</label>
<input type="text" value="johndoe" class="vt-input vt-border-success-fill vt-focus-visible:ring-success-fill" id="form-3-2">
<p class="vt-text-xs vt-text-success-fill vt-flex vt-items-center vt-gap-1">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-check vt-w-3 vt-h-3">
<path d="M20 6 9 17l-5-5"></path>
</svg>
Username is available
</p>
</div>
</div>
Horizontal Layout
Label and input on the same row for settings-style forms.
<div class="vt-w-full vt-max-w-lg vt-space-y-4">
<div class="vt-flex vt-items-center vt-gap-4">
<label class="vt-text-sm vt-font-medium vt-w-32 vt-shrink-0 vt-text-right" for="form-4-1">Full Name</label>
<input type="text" value="John Doe" class="vt-input vt-flex-1" id="form-4-1">
</div>
<div class="vt-flex vt-items-center vt-gap-4">
<label class="vt-text-sm vt-font-medium vt-w-32 vt-shrink-0 vt-text-right" for="form-4-2">Email</label>
<input type="email" value="john@example.com" class="vt-input vt-flex-1" id="form-4-2">
</div>
<div class="vt-flex vt-items-center vt-gap-4">
<label class="vt-text-sm vt-font-medium vt-w-32 vt-shrink-0 vt-text-right" for="form-4-3">Role</label>
<select class="vt-input vt-flex-1 vt-appearance-none" id="form-4-3">
<option>Developer</option>
<option>Designer</option>
<option>Manager</option>
</select>
</div>
<div class="vt-flex vt-justify-end">
<button type="button" class="vt-btn vt-btn-primary">Save Changes</button>
</div>
</div>
Registration Form
Complete registration form with multiple field types.
Create Account
Fill in your details to get started
Guidelines
Form scaffolding: field stacks with labels, helpers and validation slots.
Please enter a valid email address
Anatomy
HTML structure of the Form component.
form ← Form element
└── div.vt-space-y-1.5 ← Field group
├── label ← Field label
├── div.vt-relative ← Input wrapper (for icon)
│ ├── svg ← Leading icon (optional)
│ └── input.vt-input ← Input field
└── p.vt-field-description ← Helper / error message
└── button.vt-btn.vt-btn-primary ← Submit button
API Reference
All CSS classes available for the Form component.
| Class | Type | Description |
|---|---|---|
vt-space-y-4 |
Spacing | Vertical spacing between form fields |
vt-space-y-1.5 |
Spacing | Tight spacing between label, input, and hint |
vt-text-sm vt-font-medium |
Typography | Form label text style |
vt-h-10 vt-rounded-lg |
Shape | Input height and border radius |
vt-border vt-border-border-strong |
Border | Default input border |
vt-bg-surface-card |
Color | Input background color |
vt-focus-visible:ring-1 vt-focus-visible:ring-info-fill |
State | Blue focus ring on input focus |
vt-border-error-fill |
State | Red border for error state inputs |
vt-focus-visible:ring-error-fill |
State | Red focus ring for error state |
vt-border-success-fill |
State | Green border for success state inputs |
vt-text-error-fill |
Color | Red text for error messages |
vt-text-success-fill |
Color | Green text for success messages |
vt-text-foreground-muted |
Color | Muted text for hint/helper text |
vt-btn vt-btn-primary vt-w-full |
Component | Full-width primary submit button |
vt-checkbox |
Component | Styled checkbox input |
Accessibility
Keyboard and screen reader support.
| Feature | Details |
|---|---|
| Labels | Every input must have a visible label linked via for/id attributes |
| Errors | Error messages linked via aria-describedby, invalid fields use aria-invalid="true" |
| Required | Required fields should use required attribute and aria-required="true" |
| Groups | Related fields wrapped in fieldset with legend element |
| Submit | Form submission feedback should be announced to screen readers |