Field
The wrapper that binds a label, a control and an error message into one form row.
<x-atlas::field>
Every Atlas form is built from fields. A field is a plain block wrapper: it sets the type scale for its contents and gives the row a predictable width, then leaves the arrangement to the components inside it. Start here, then reach for label, input and error to fill it.
<x-atlas::field>
<x-atlas::label for="full-name">Full name</x-atlas::label>
<x-atlas::input id="full-name" name="full_name" type="text" placeholder="Ada Lovelace" />
</x-atlas::field>
<atlas-label>, not a native <label>, so a
for attribute is inert. Point the control at the label with
aria-labelledby — see pairing with the
control.
Errors
An invalid value needs three things said at once: mark the control with invalid
so it turns red and gains aria-invalid, put the reason in an
error, and point the control at that error with
aria-describedby so a screen reader reads the two together.
<x-atlas::field>
<x-atlas::label for="work-email" is-required>Work email</x-atlas::label>
<x-atlas::input
id="work-email"
name="work_email"
type="email"
value="ada@"
aria-describedby="work-email-error"
invalid
/>
<x-atlas::error id="work-email-error">Enter an email address, including the part after the @.</x-atlas::error>
</x-atlas::field>
Any control
Anything that can be labelled belongs in a field — input, textarea, select. Wrapping every control the same way is what keeps a long form from drifting out of rhythm.
<x-atlas::field>
<x-atlas::label for="department">Department</x-atlas::label>
<x-atlas::select id="department" name="department">
<x-atlas::select.option value="design">Design</x-atlas::select.option>
<x-atlas::select.option value="engineering">Engineering</x-atlas::select.option>
<x-atlas::select.option value="support">Support</x-atlas::select.option>
</x-atlas::select>
</x-atlas::field>
<x-atlas::field>
<x-atlas::label for="handover">Handover notes</x-atlas::label>
<x-atlas::textarea id="handover" name="handover" rows="4" placeholder="Anything the next person needs to know" />
</x-atlas::field>
Inline
variant="inline" lays the label out beside the control instead of above it,
collapsing back to a stack under 768px. Use it for short, self-evident values — a quantity,
a date — where a full-width label would waste a line. Anything that needs a hint or an error
reads better stacked. Each label sizes to its own text, so stacked inline fields will not line
their controls up in a column; give the labels a shared width yourself if that matters.
<x-atlas::field variant="inline">
<x-atlas::label for="seats">Seats</x-atlas::label>
<x-atlas::input id="seats" name="seats" type="number" value="4" min="1" max="20" />
</x-atlas::field>
<x-atlas::field variant="inline">
<x-atlas::label for="starts-on">Starts on</x-atlas::label>
<x-atlas::input id="starts-on" name="starts_on" type="date" value="2026-09-01" />
</x-atlas::field>
inline is the only variant with styles in Atlas. Any other value still lands on
the element as an atlas-field--{variant} class, so it is a hook for your own
CSS rather than something the package will style for you.
A whole form
Fields stack; a fieldset gathers the ones that belong together and a legend names the group. That is the entire layout system — there is no grid or column prop to learn.
<x-atlas::fieldset role="group" aria-labelledby="delivery-legend">
<x-atlas::legend id="delivery-legend">Delivery address</x-atlas::legend>
<x-atlas::field>
<x-atlas::label for="street" is-required>Street and number</x-atlas::label>
<x-atlas::input id="street" name="street" type="text" placeholder="Keizersgracht 123" required />
</x-atlas::field>
<x-atlas::field>
<x-atlas::label for="postcode" is-required>Postcode</x-atlas::label>
<x-atlas::input id="postcode" name="postcode" type="text" placeholder="1015 CJ" required />
</x-atlas::field>
<x-atlas::field>
<x-atlas::label for="country">Country</x-atlas::label>
<x-atlas::select id="country" name="country">
<x-atlas::select.option value="nl">Netherlands</x-atlas::select.option>
<x-atlas::select.option value="be">Belgium</x-atlas::select.option>
<x-atlas::select.option value="de">Germany</x-atlas::select.option>
</x-atlas::select>
</x-atlas::field>
<x-atlas::button type="submit">Save address</x-atlas::button>
</x-atlas::fieldset>
Related components
Label
The name of a form control, with an optional required marker.
Input
A single-line text control, styled for every input type the browser offers.
Textarea
A multi-line text control that shares the input styling, with a resize handle you can lock down.
Error
The message that explains why a control was rejected, with a warning icon in front of it.
Fieldset
A vertical stack that gathers related fields into one group.
Legend
The heading that names a fieldset.
Select
A native select styled with Atlas input tokens, with a disabled placeholder option built in.
Checkbox
A checkbox with a styled indicator, an optional description and a card-like grouped layout.
Radio
A native radio button with a styled indicator, plus a group wrapper for the set it belongs to.
Toggle
A switch that turns something on or off immediately, implementing the full ARIA switch pattern in Alpine over a hidden checkbox.
Reference
<x-atlas::field>
-
- Name
variant- Type
- string
- Default
- default: (none)
- Description
- Appended as an <code>atlas-field--{variant}</code> modifier class. <code>inline</code> is the only variant Atlas ships styles for; it lays the label out beside the control and stacks again under 768px.
Slots
-
- Name
default- Type
- slot
- Description
- The label, the control and — when the value is rejected — the error, in that order.