Input
A text input field with focus ring and disabled state.
<input x-data="input()" x-bind="inputAttrs" type="email" placeholder="Email" />
<input x-data="input({ state: 'disabled' })" x-bind="inputAttrs" type="email" disabled />
<input x-data="input({ class: 'pl-9' })" x-bind="inputAttrs" type="email" placeholder="With icon" />
Usage
<!-- Basic input -->
<input x-data="input()" x-bind="inputAttrs" type="email" placeholder="Email" />
<!-- Input with label and description (using Field) -->
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Email</label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="email" placeholder="you@example.com" />
<p x-data="fieldDescription()" x-bind="fieldDescriptionAttrs">We'll never share your email.</p>
</div>
</div>
<!-- Invalid input -->
<div x-data="field({ invalid: true })" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Email</label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="email" value="invalid" aria-invalid="true" />
<p x-data="fieldDescription()" x-bind="fieldDescriptionAttrs" class="text-destructive">Please enter a valid email.</p>
</div>
</div>
<!-- Input Group (prefix/suffix) -->
<div x-data="inputGroup()" x-bind="inputGroupAttrs">
<div x-data="inputGroupAddon({ align: 'inline-start' })" x-bind="inputGroupAddonAttrs">
<svg>...</svg>
</div>
<input x-data="inputGroupInput()" x-bind="inputGroupInputAttrs" type="url" placeholder="Website" />
<div x-data="inputGroupAddon({ align: 'inline-end' })" x-bind="inputGroupAddonAttrs">
<span>https://</span>
</div>
</div>
<!-- Field Group (grid layout) -->
<div x-data="fieldGroup()" x-bind="fieldGroupAttrs">
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">First Name</label>
<input x-data="input()" x-bind="inputAttrs" type="text" />
</div>
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Last Name</label>
<input x-data="input()" x-bind="inputAttrs" type="text" />
</div>
</div>
Examples
Field
Use field(), fieldContent(), and fieldDescription() to build inputs with labels and helper text.
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Username</label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="text" placeholder="Choose a username" />
<p x-data="fieldDescription()" x-bind="fieldDescriptionAttrs">Choose a unique username.</p>
</div>
</div>
Invalid
Use invalid: true on the field and aria-invalid="true" on the input to show validation errors.
<div x-data="field({ invalid: true })" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Invalid Input</label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="text" value="bad data" aria-invalid="true" />
<p x-data="fieldDescription()" x-bind="fieldDescriptionAttrs" class="text-destructive">This field contains validation errors.</p>
</div>
</div>
File
Use type="file" to create a file input.
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Picture</label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="file" />
<p x-data="fieldDescription()" x-bind="fieldDescriptionAttrs">Select a picture to upload.</p>
</div>
</div>
Inline
Use orientation="horizontal" on a field to create an inline input paired with a button.
<div x-data="field({ class: 'flex-row items-end gap-3' })" x-bind="fieldAttrs">
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<label x-data="label()" x-bind="labelAttrs">Search</label>
<input x-data="input()" x-bind="inputAttrs" type="search" placeholder="Search..." />
</div>
<button x-data="button({ variant: 'default' })" x-bind="buttonAttrs">
<svg ...>...</svg>
Search
</button>
</div>
Grid
Use fieldGroup to place multiple fields side by side.
<div x-data="fieldGroup()" x-bind="fieldGroupAttrs">
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">First Name</label>
<input x-data="input()" x-bind="inputAttrs" type="text" placeholder="John" />
</div>
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Last Name</label>
<input x-data="input()" x-bind="inputAttrs" type="text" placeholder="Doe" />
</div>
</div>
Required
Use the required attribute and add a visual indicator to the label.
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Required Field <span class="text-destructive">*</span></label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="text" placeholder="Type something..." required />
<p x-data="fieldDescription()" x-bind="fieldDescriptionAttrs">This field must be filled out.</p>
</div>
</div>
Badge
Add a badge inside the label to highlight a recommended field.
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">
Webhook URL
<span x-data="badge({ variant: 'secondary' })" x-bind="badgeAttrs">Beta</span>
</label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="url" placeholder="https://example.com/webhook" />
</div>
</div>
Input Group
Use inputGroup and inputGroupAddon to add icons, text, or buttons inside an input.
<div x-data="inputGroup()" x-bind="inputGroupAttrs">
<div x-data="inputGroupAddon({ align: 'inline-start' })" x-bind="inputGroupAddonAttrs">
<svg>...</svg>
</div>
<input x-data="inputGroupInput()" x-bind="inputGroupInputAttrs" type="url" placeholder="Website URL" />
<div x-data="inputGroupAddon({ align: 'inline-end' })" x-bind="inputGroupAddonAttrs">
<span>https://</span>
</div>
</div>
Button Group
Use buttonGroup to attach buttons to an input.
<div x-data="inputGroup()" x-bind="inputGroupAttrs">
<input x-data="inputGroupInput()" x-bind="inputGroupInputAttrs" type="search" placeholder="Search..." />
<div x-data="inputGroupAddon({ align: 'inline-end' })" x-bind="inputGroupAddonAttrs" class="p-0! [&>button]:my-1">
<button x-data="button({ variant: 'ghost', size: 'icon-sm' })" x-bind="buttonAttrs" class="rounded-[calc(var(--radius)-5px)]!">
<svg>...</svg>
</button>
</div>
</div>
Form
A complete form combining multiple input types.
<div x-data="fieldGroup()" x-bind="fieldGroupAttrs">
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Name</label>
<input x-data="input()" x-bind="inputAttrs" type="text" placeholder="Your name" />
</div>
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Email</label>
<input x-data="input()" x-bind="inputAttrs" type="email" placeholder="you@example.com" />
</div>
</div>
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Email</label>
<div x-data="fieldContent()" x-bind="fieldContentAttrs">
<input x-data="input()" x-bind="inputAttrs" type="email" placeholder="you@example.com" />
<p x-data="fieldDescription()" x-bind="fieldDescriptionAttrs">We'll never share your email.</p>
</div>
</div>
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Phone</label>
<input x-data="input()" x-bind="inputAttrs" type="tel" placeholder="+1 (555) 000-0000" />
</div>
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Country</label>
<select class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs md:text-sm focus-visible:border-ring focus-visible:ring-[3px] dark:bg-input/30">
<option>United States</option>
<option>Canada</option>
<option>Mexico</option>
</select>
</div>
<div x-data="fieldGroup()" x-bind="fieldGroupAttrs">
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Address</label>
<input x-data="input()" x-bind="inputAttrs" type="text" placeholder="Street" />
</div>
<div x-data="field()" x-bind="fieldAttrs">
<label x-data="label()" x-bind="labelAttrs">Zip</label>
<input x-data="input()" x-bind="inputAttrs" type="text" placeholder="ZIP" />
</div>
</div>
<div class="flex justify-end gap-2">
<button x-data="button({ variant: 'outline' })" x-bind="buttonAttrs">Cancel</button>
<button x-data="button({ variant: 'default' })" x-bind="buttonAttrs">Submit</button>
</div>