Input

A light wrapper around the native input element that handles tedious accessibility concerns and provides more opinionated states for things like hover and focus.

To get started, install Headless UI via npm:

npm install @headlessui/react

Inputs are built using the Input component:

import { Input } from '@headlessui/react'

function Example() {
  return <Input name="full_name" type="text" />
}

You can pass any props to an Input that you'd normally pass to the native input element.

Headless UI keeps track of a lot of state about each component, like whether or not an input is focused, whether a popover is open or closed, or which item in a menu is currently focused via the keyboard.

But because the components are headless and completely unstyled out of the box, you can't see this information in your UI until you provide the styles you want for each state yourself.

The easiest way to style the different states of a Headless UI component is using the data-* attributes that each component exposes.

For example, the Input component exposes a data-focus attribute, which tells you if the input is currently focused via the mouse or keyboard, and a data-hover attribute, which tells you if the input is currently being hovered by the mouse.

<!-- Rendered `Input` -->
<input type="text" name="full_name" data-focus data-hover />

Use the CSS attribute selector to conditionally apply styles based on the presence of these data attributes. If you're using Tailwind CSS, the data attribute modifier makes this easy:

import { Input } from '@headlessui/react'

function Example() {
return <Input type="text" name="full_name" className="border data-[hover]:shadow data-[focus]:bg-blue-100" />
}

See the component API for a list of all the available data attributes.

Each component also exposes information about its current state via render props that you can use to conditionally apply different styles or render different content.

For example, the Input component exposes a focus state, which tells you if the input is currently focused via the mouse or keyboard, and a hover state, which tells you if the input is currently being hovered by the mouse.

import { Input } from '@headlessui/react'
import clsx from 'clsx'
import { Fragment } from 'react'

function Example() {
  return (
    <Input type="text" name="full_name" as={Fragment}>
{({ focus, hover }) => <input className={clsx('border', focus && 'bg-blue-100', hover && 'shadow')} />}
</Input> ) }

See the component API for a list of all the available render props.

Wrap a Label and Input with the Field component to automatically associate them using a generated ID:

import { Field, Input, Label } from '@headlessui/react'

function Example() {
  return (
<Field>
<Label>Name</Label>
<Input name="full_name" />
</Field>
) }

Use the Description component within a Field to automatically associate it with an Input using the aria-describedby attribute:

import { Description, Field, Input, Label } from '@headlessui/react'

function Example() {
  return (
<Field>
<Label>Name</Label>
<Description>Use your real name so people will recognize you.</Description>
<Input name="full_name" />
</Field>
) }

Add the disabled prop to the Field component to disable an Input and its associated Label and Description:

import { Description, Field, Input, Label } from '@headlessui/react'

function Example() {
  return (
<Field disabled>
<Label className="data-[disabled]:opacity-50">Name</Label> <Description className="data-[disabled]:opacity-50">Use your real name so people will recognize you.</Description> <Input name="full_name" className="data-[disabled]:bg-gray-100" /> </Field> ) }

You can also disable an input outside of a Field by adding the disabled prop directly to the Input itself.

A thin wrapper around the native input element.

PropDefaultDescription
asinput
String | Component

The element or component the input should render as.

invalidfalse
Boolean

Whether or not the input is invalid.

disabledfalse
Boolean

Whether or not the input is disabled.

autoFocusfalse
Boolean

Whether or not the input should receive focus when first rendered.

Data AttributeRender PropDescription
data-invalidinvalid

Boolean

Whether or not the input is invalid.

data-disableddisabled

Boolean

Whether or not the input is disabled.

data-focusfocus

Boolean

Whether or not the input is focused.

data-hoverhover

Boolean

Whether or not the input is hovered.

data-autofocusautofocus

Boolean

Whether or not the autoFocus prop was set to true.

Groups a Label, Description, and form control together.

PropDefaultDescription
asdiv
String | Component

The element or component the field should render as.

disabledfalse
Boolean

Whether or not the field is disabled.

Data AttributeRender PropDescription
data-disableddisabled

Boolean

Whether or not the field is disabled.

The Label component labels a form control.

PropDefaultDescription
aslabel
String | Component

The element or component the label should render as.

passivefalse
Boolean

When true, clicking the label won't focus the associated form control.

Data AttributeRender PropDescription
data-disableddisabled

Boolean

Whether or not the parent Field is disabled.

The Description component describes a form control.

PropDefaultDescription
asp
String | Component

The element or component the description should render as.

Data AttributeRender PropDescription
data-disableddisabled

Boolean

Whether or not the parent Field is disabled.

If you're interested in predesigned Tailwind CSS form input group examples, check out Tailwind UI — a collection of beautifully designed and expertly crafted components built by us.

It's a great way to support our work on open-source projects like this and makes it possible for us to improve them and keep them well-maintained.