Component demo // Forms
Inputs, labels and validation — all from the forms layer.
Text fields, selects, checkboxes and radios share spacing tokens for comfortable density and consistent error surfaces.
Act I // Primitives
Text fields, selects, checkboxes and radios built on shared density tokens.
Every form primitive inherits block spacing and inline padding from the same token layer, so swapping one control for another never breaks the layout rhythm.
<label class="vl-field">
<span class="vl-field__label">Email</span>
<input class="vl-input" type="email"
aria-describedby="email-hint" />
<span class="vl-field__hint" id="email-hint">We’ll never share it.</span>
</label>
vl-field is the density wrapper — change --vl-density once and every primitive in the form reflows together.
Act II // Validation
Error surfaces and text colors from semantic tokens.
Validation states map to --vl-signal-danger and
--vl-signal-success, keeping feedback consistent
across every theme without overrides.
--vl-form-border-error: var(--vl-signal-danger);
--vl-form-text-error: var(--vl-signal-danger);
--vl-form-bg-error: var(--vl-signal-danger / 0.08);
Tokens, not colors.
Point to semantic aliases so every theme gets correct error surfaces for free.
Act III // Motion
Optional reveal for inline errors keeps forms calm.
Error messages use vl-effect="fade-up" with a short duration
so they slide in without startling the user. Motion is progressive:
if CSS Motion is unsupported the message simply appears.
-
Error reveal
fade-up · 200 ms
-
Success check
spring-3d · 300 ms
-
Focus ring
depth-push · 150 ms
Act IV // Applied forms
Primitives, validation and motion: one token layer for every input.
Start with shared density tokens, add semantic validation surfaces, then sprinkle progressive motion for a polished, accessible form experience.