Button
An augmented native <button> primitive. Built with native-first press logic, keyboard support, robust state-driven data attributes, and a focus-visible polyfill. Zero CSS shipped.
Features
- Native-first use-press logic that replicates browser interactions.
- Provides logical focus and pointer-aware states like hovered and pressed.
- Fully accessible, managing disabled and pending states natively.
- First-class DOM rendering composition via the `render` prop.
- Zero CSS shipped — target semantic data-attributes to style.
Installation
Install the Button primitive on its own, or use the aggregator @kenos-ui/react package if you already depend on other Kenos primitives.
Install a package
npm install @kenos-ui/react-buttonnpm install @kenos-ui/reactImport
import { Button } from "@kenos-ui/react-button";import { Button } from "@kenos-ui/react";Examples
Every demo is interactive and keyboard-navigable.
Default
The base usage — provides data-hovered, data-pressed, and data-focused out of the box. Toggle the code tabs to see unstyled, CSS, Tailwind, Panda CSS, and StyleX approaches.
Pending State
Set isPending to indicate loading state. The button maintains focusability, blocks action (onClick/onPress), and announces via aria-busy. It exposes data-pending for styling.
Disabled State
Set isDisabled for semantic disabling. It prevents interaction and uses aria-disabled instead of native disabled so that the button is not implicitly removed from the accessibility tree, allowing screen readers to still discover it. It exposes data-disabled for styling.
Render Props Composition
If you need to change the DOM node or integrate directly with the internal state, pass a function to the render prop. This allows you to apply inline styles based on state.isHovered or state.isPressed.
Advanced Behaviors
The button intentionally avoids "magic props" for complex behaviors. Instead, we export specialized hooks that you can compose manually via composeEventHandlers. This keeps the component API lean while giving you full control over when and how these effects trigger.
Available hooks include useHaptics, useLongPress, useHover, and usePointerPressure.
useHaptics
Triggers a vibration on supported devices using semantic intents. Combine it with your onClick using composeEventHandlers.
useLongPress
Tracks pointer events to trigger an action after a specified delay (default 500ms). It automatically cancels if the pointer leaves or is released early, and prevents the default click if the long press was successful.
useHover
A utility hook that tracks hover state reliably across devices, avoiding "sticky hover" on touch devices. It returns the current state and the props to spread onto the element.
Accessibility
Kenos enhances the native button accessibility. Roles, labels, and state management (like pending/disabled) are handled for you natively via aria-disabled and aria-busy.
Roles and attributes
| Part | Role / Attributes |
|---|---|
| Button | button |
Keyboard support
| Key | Description |
|---|---|
| Enter | Activates the button. |
| Space | Activates the button. Prevents page scrolling when pressed. |
API Reference
Props and data attributes. Import from @kenos-ui/react-button.
Root props
falseLoading state. Maintains focusability, blocks action, announces via aria-busy.
falseSemantic equivalent to `disabled`, explicitly named for intent clarity. Uses aria-disabled internally.
falseRemoves from tab order without using native `disabled`.
falsePrevents focus from moving to the button on press (mouse/touch).
Replaces the rendered DOM element, keeping behavior and props.
Data attributes
| Attribute | On part | Description |
|---|---|---|
| [data-hovered] | Present when the button is hovered with mouse. | |
| [data-pressed] | Present when the button is actively pressed. | |
| [data-focused] | Present when the button has logical focus. | |
| [data-pending] | Present when the button is in a pending/loading state. | |
| [data-disabled] | Present when the button is semantically disabled. |