Input
If web applications didn't need inputs, computers wouldn't have keyboards.
<script>
import { Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
</script>
<Field>
<Label>Full name</Label>
<Input name="full_name" />
</Field> Component API
| Prop | Default | Description |
|---|---|---|
Input extends the Headless UI <Input> component | ||
disabled | false | Whether or not to disable the input. |
invalid | false | Whether or not the input has a validation error. |
name | - | The name to use when submitting an HTML form. |
defaultValue | - | The initial value for the input. |
value | - | The controlled value of the input. |
onChange | - | Handler to call when the input value changes. |
Field extends the Headless UI <Field> component | ||
disabled | false | Whether or not to disable the entire field. |
Label extends the Headless UI <Label> component | ||
| This component does not expose any component-specific props. | ||
Description extends the Headless UI <Description> component | ||
| This component does not expose any component-specific props. | ||
ErrorMessage extends the Headless UI <Description> component | ||
| This component does not expose any component-specific props. | ||
Examples
Basic example
Use the Input component on its own to render a standalone input without an associated Label component:
<script>
import { Input } from '$lib/components/input';
</script>
<Input aria-label="Full name" name="full_name" /> Make sure to provide an aria-label for assistive technology, or connect the Input to your own <label> element using an id.
With label
Wrap a Label and Input with the Field component to automatically associate them using a generated ID:
<script>
import { Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
</script>
<Field>
<Label>Full name</Label>
<Input name="full_name" />
</Field> With description
Use the Description component to add a description above or below your Input:
Use the name you'd like people to see in their cart.
<script>
import { Description, Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
</script>
<Field>
<Label>Product name</Label>
<Description>Use the name you'd like people to see in their cart.</Description>
<Input name="product_name" />
</Field> With icon
Wrap an icon and Input with the InputGroup component to render an input with an icon:
<script>
import { Input, InputGroup } from '$lib/components/input';
import HeroiconsMagnifyingGlass16Solid from 'virtual:icons/heroicons/magnifying-glass-16-solid';
</script>
<InputGroup>
<HeroiconsMagnifyingGlass16Solid />
<Input name="search" placeholder="Search…" aria-label="Search" />
</InputGroup> The InputGroup component is designed to work best with 16×16 icons.
Setting the type
Use the type prop to set the input type to any supported text input type:
<script>
import { Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
</script>
<Field>
<Label>Your website</Label>
<Input type="url" name="url" />
</Field> The supported types are email, number, password, search, tel, text, url, date, datetime-local, month, time, and week.
Disabled state
Add the disabled prop to the Field component to disable an Input and the associated Label:
<script>
import { Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
</script>
<Field disabled>
<Label>Full name</Label>
<Input name="full_name" />
</Field> You can also disable an input outside of a Field by adding the disabled prop directly to the Input itself.
Validation errors
Add the invalid prop to the Input component to indicate a validation error, and render the error using the ErrorMessage component:
This field is required.
<script>
import { ErrorMessage, Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
</script>
<Field>
<Label>Full name</Label>
<Input name="full_name" invalid={errors.has('full_name')} />
{#if errors.has('full_name')}
<ErrorMessage>{errors.get('full_name')}</ErrorMessage>
{/if}
</Field> Constraining width
Use the class prop on the Input component to make layout adjustments like adjusting the max-width:
<script>
import { Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
</script>
<Field>
<Label>CVC</Label>
<Input class="max-w-[6rem]" name="cvc" pattern="[0-9]*" />
</Field> Be aware that the class prop is a sharp knife — make sure to only add classes that don't conflict with classes the component already includes or you'll get unexpected results.
With custom layout
Use the unstyled Field component from @headlessui/react directly instead of the styled Field component to implement a custom layout:
<script>
import { Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
import * as Headless from '@headlessui/react';
</script>
<Headless.Field class="flex items-center justify-center gap-6">
<Label>Full name</Label>
<Input name="full_name" class="max-w-48" />
</Headless.Field> Using the unstyled Field component will ensure important accessibility features are still handled for you like generating IDs and associating elements using aria-* attributes.
Controlled component
Use the normal value and onChange props to use the Input component as a controlled component:
<script>
import { Field, Label } from '$lib/components/fieldset';
import { Input } from '$lib/components/input';
let name = $state('');
</script>
<Field>
<Label>Full name</Label>
<Input name="full_name" bind:value={name} />
</Field>