React hooks for implementing accessible button components with comprehensive keyboard, mouse, and touch interaction handling.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Provides fundamental button behavior with accessibility, press state management, and support for multiple element types. The useButton hook handles all interactions for button components across different HTML elements while maintaining ARIA compliance.
Creates accessible button behavior for any HTML element with comprehensive interaction handling.
/**
* Provides the behavior and accessibility implementation for a button component.
* Handles mouse, keyboard, and touch interactions, focus behavior, and ARIA props
* for both native button elements and custom element types.
* @param props - Props to be applied to the button
* @param ref - A ref to a DOM element for the button
*/
function useButton(props: AriaButtonOptions<'button'>, ref: RefObject<HTMLButtonElement | null>): ButtonAria<ButtonHTMLAttributes<HTMLButtonElement>>;
function useButton(props: AriaButtonOptions<'a'>, ref: RefObject<HTMLAnchorElement | null>): ButtonAria<AnchorHTMLAttributes<HTMLAnchorElement>>;
function useButton(props: AriaButtonOptions<'div'>, ref: RefObject<HTMLDivElement | null>): ButtonAria<HTMLAttributes<HTMLDivElement>>;
function useButton(props: AriaButtonOptions<'input'>, ref: RefObject<HTMLInputElement | null>): ButtonAria<InputHTMLAttributes<HTMLInputElement>>;
function useButton(props: AriaButtonOptions<'span'>, ref: RefObject<HTMLSpanElement | null>): ButtonAria<HTMLAttributes<HTMLSpanElement>>;
function useButton(props: AriaButtonOptions<ElementType>, ref: RefObject<Element | null>): ButtonAria<DOMAttributes>;Usage Examples:
import { useButton } from "@react-aria/button";
import { useRef } from "react";
// Basic button element
function Button(props) {
let ref = useRef<HTMLButtonElement | null>(null);
let { buttonProps, isPressed } = useButton(props, ref);
return (
<button {...buttonProps} ref={ref}>
{props.children}
</button>
);
}
// Custom element with proper ARIA
function CustomButton(props) {
let ref = useRef<HTMLSpanElement | null>(null);
let { buttonProps, isPressed } = useButton({
...props,
elementType: 'span'
}, ref);
return (
<span
{...buttonProps}
style={{
background: isPressed ? 'darkblue' : 'blue',
color: 'white',
padding: 10,
cursor: 'pointer',
userSelect: 'none'
}}
ref={ref}>
{props.children}
</span>
);
}
// Link button
function LinkButton(props) {
let ref = useRef<HTMLAnchorElement | null>(null);
let { buttonProps } = useButton({
...props,
elementType: 'a',
href: props.href
}, ref);
return (
<a {...buttonProps} ref={ref}>
{props.children}
</a>
);
}Configuration options for button behavior and appearance.
interface AriaButtonOptions<E extends ElementType> extends Omit<AriaButtonProps<E>, 'children'> {
/** The HTML element or React element used to render the button. @default 'button' */
elementType?: E | JSXElementConstructor<any>;
/** Whether the button is disabled. */
isDisabled?: boolean;
/** Handler that is called when the press is released over the target. */
onPress?: (e: PressEvent) => void;
/** Handler that is called when a press interaction starts. */
onPressStart?: (e: PressEvent) => void;
/** Handler that is called when a press interaction ends, either over the target or when the pointer leaves the target. */
onPressEnd?: (e: PressEvent) => void;
/** Handler that is called when the press state changes. */
onPressChange?: (isPressed: boolean) => void;
/** Handler that is called when a press is released over the target, regardless of whether it started on the target or not. */
onPressUp?: (e: PressEvent) => void;
/** Whether to prevent focus from moving to the button when pressing it. */
preventFocusOnPress?: boolean;
/** Standard onClick handler (called in addition to onPress). */
onClick?: (e: MouseEvent) => void;
/** A URL to link to if elementType="a". */
href?: string;
/** The target window for the link. */
target?: string;
/** The relationship between the linked resource and the current page. */
rel?: string;
/** The behavior of the button when used in an HTML form. @default 'button' */
type?: 'button' | 'submit' | 'reset';
/** The `<form>` element to associate the button with. */
form?: string;
/** The URL that processes the information submitted by the button. */
formAction?: string;
/** Indicates how to encode the form data that is submitted. */
formEncType?: string;
/** Indicates the HTTP method used to submit the form. */
formMethod?: string;
/** Indicates that the form is not to be validated when it is submitted. */
formNoValidate?: boolean;
/** Overrides the target attribute of the button's form owner. */
formTarget?: string;
/** Submitted as a pair with the button's value as part of the form data. */
name?: string;
/** The value associated with the button's name when it's submitted with the form data. */
value?: string;
}Return value from the useButton hook containing props and state.
interface ButtonAria<T> {
/** Props for the button element. */
buttonProps: T;
/** Whether the button is currently pressed. */
isPressed: boolean;
}The useButton hook supports multiple HTML element types, each with appropriate handling:
elementType: 'button')elementType: 'a')elementType: 'div' | 'span')elementType: 'input')The hook provides normalized event handling across all interaction methods:
When using with native button elements, full HTML form support is provided:
form attributeformNoValidate)Install with Tessl CLI
npx tessl i tessl/npm-react-aria--button