Button
A light wrapper around the native button element that provides more opinionated states for things like hover and focus.
To get started, install Headless UI via npm:
npm install @headlessui/react
Buttons are built using the Button
component:
import { Button } from '@headlessui/react'
function Example() {
return (
<Button className="rounded bg-sky-600 py-2 px-4 text-sm text-white data-[hover]:bg-sky-500 data-[active]:bg-sky-700">
Save changes
</Button>
)
}
You can pass any props to a Button
that you'd normally pass to the native button
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 Button
component exposes a data-hover
attribute, which tells you if the button is currently being
hovered by the mouse, and a data-active
attribute, which tells you if the button is currently being pressed.
<!-- Rendered `Button` -->
<button type="button" data-hover data-active></button>
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 { Button } from '@headlessui/react'
function Example() {
return (
<Button className="rounded bg-sky-600 py-2 px-4 text-sm text-white data-[hover]:bg-sky-500 data-[hover]:data-[active]:bg-sky-700"> Save changes
</Button>
)
}
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 Button
component exposes a hover
state, which tells you if the button is currently being hovered by
the mouse, and an active
state, which tells you if the button is currently being pressed.
import { Button } from '@headlessui/react'
import clsx from 'clsx'
import { Fragment } from 'react'
function Example() {
return (
<Button as={Fragment}>
{({ hover, active }) => ( <button
className={clsx(
'rounded py-2 px-4 text-sm text-white',
!hover && !active && 'bg-sky-600', hover && !active && 'bg-sky-500', active && 'bg-sky-700' )}
>
Save changes
</button>
)} </Button>
)
}
See the component API for a list of all the available render props.
Add the disabled
prop to a Button
to disable it:
import { Button } from '@headlessui/react'
function Example() {
return (
<Button
disabled className="rounded bg-sky-600 py-2 px-4 text-sm text-white data-[hover]:bg-sky-500 data-[active]:bg-sky-700 data-[disabled]:bg-gray-500"
>
Save changes
</Button>
)
}
A thin wrapper around the native button
element.
Prop | Default | Description |
as | button | String | Component The element or component the button should render as. |
disabled | false | Boolean Whether or not the button is disabled. |
autoFocus | false | Boolean Whether or not the button should receive focus when first rendered. |
type | button | String The button type. |
Data Attribute | Render Prop | Description |
data-disabled | disabled |
Whether or not the button is disabled. |
data-focus | focus |
Whether or not the button is focused. |
data-hover | hover |
Whether or not the button is hovered. |
data-active | active |
Whether or not the button is in an active or pressed state. |
data-autofocus | autofocus |
Whether or not the |
If you're interested in predesigned Tailwind CSS button component 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.