useInteractiveState
Tracks hover, keyboard focus, and press state for any element. Returns event handlers to spread onto the element along with matching data-* attributes so consumers can style state transitions with CSS selectors.
This is the same primitive used internally by Button, Accordion.Trigger, Modal.Close, and Drawer.Close — exported so your own interactive components can opt into identical state tracking.
Unlike libraries that expose data-focus for any focus event, Wire UI uses data-focus-visible, which only applies when focus arrives from keyboard navigation — mirroring the CSS :focus-visible pseudo-class detected via element.matches(':focus-visible').
import { useInteractiveState } from '@wire-ui/react'
function Card({ disabled }: { disabled?: boolean }) {
const { handlers, dataAttributes } = useInteractiveState({ disabled })
return (
<div
tabIndex={0}
role="button"
{...handlers}
{...dataAttributes}
className="
rounded-lg border p-4 cursor-pointer transition-all
data-[hover]:bg-gray-50
data-[active]:scale-95
data-[focus-visible]:ring-2
data-[disabled]:opacity-50 data-[disabled]:pointer-events-none
"
>
Card content
</div>
)
}Options
| Option | Type | Description |
|---|---|---|
disabled | boolean | When true, suppresses hover and active state and applies data-disabled. |
Returns
| Key | Type | Description |
|---|---|---|
handlers | object | Event handlers to spread onto the element. |
dataAttributes | object | data-hover, data-focus-visible, data-active, data-disabled (each present-or-absent). |
isHovered | boolean | Raw hover state. |
isFocusVisible | boolean | Raw keyboard-focus state. |
isActive | boolean | Raw press state. |
Data attributes
| Attribute | Present when |
|---|---|
data-hover | The pointer is hovering the element (suppressed while disabled). |
data-focus-visible | The element has keyboard focus. |
data-active | The element is being pressed (pointer or Enter / Space). |
data-disabled | disabled option is truthy. |
Last updated on