Forms
Layout primitives for building forms. Composes the existing field components (Input, Select, Checkbox, Radio, Switch, DatePicker, Phone, Dropdown, MultiSelect) with consistent spacing, labels, hints, errors, required indicators. Four building blocks: Field, Field Group (fieldset + legend), Form (parent shell), and Horizontal layout variant for settings-style layouts.
a11y (built in): every native control is bound to its <label for>, and checkbox/radio/switch rows wrap the input inside the label itself; .lb-checkbox, .lb-radio and .lb-switch are real inputs restyled with appearance: none, so keyboard behaviour, grouping by name and the focus ring all stay native. Related fields sit in a real <fieldset> + <legend>, and an invalid field carries aria-invalid plus aria-describedby pointing at its .lb-field__error. The required marker is a CSS ::after glyph, so set required or aria-required on the control as well — the asterisk alone is styling.
Usage: Wrap fields in .lb-field (vertical default, --horizontal for label-left). Group related fields with <fieldset class="lb-field-group"> + <legend class="lb-field-group__legend">. Parent with <form class="lb-form">; put submit/cancel in .lb-form__actions.
Single field — anatomy
Label, optional required marker, input, optional hint or error/success message. Consistent spacing + typography across every input type.
Horizontal layout
Label column left (fixed 10rem), input column right. Good for settings pages and admin panels. Collapses to vertical on narrow screens (<640px).
Field group
Semantic <fieldset> with <legend> for related fields. Screen readers announce the legend before each field inside.
Full form
End-to-end example with multiple field groups + actions row. .lb-form provides consistent 24px vertical rhythm; .lb-form__actions right-aligns the submit/cancel buttons.
Validation — LB.Form
Add data-lb-validate to a <form> and the DS owns the validation behaviour on submit: required, email and URL formats on native inputs, 6–15 digits on the phone composition, and required state on DS selects and datepickers (via their own setError APIs). Errors render with the existing skin — error border, .lb-field__error message with the alert icon, aria-invalid + aria-describedby — the first invalid field is focused and scrolled into view, and each field clears live as the user types or picks. Browser bubbles are suppressed (novalidate). Per-field copy via data-lb-error-required / -email / -url / -phone; form-wide defaults via new LB.Form(el, { messages }), and onValid receives the passing submit. What happens on success — sanitization, sending — stays yours.
Form spacing
Three density levels via form modifiers. Default (24px between fields), --compact (16px, settings panels), --loose (32px, marketing signup).
.lb-form--compact.lb-form--loose