React hooks for implementing accessible button components with comprehensive keyboard, mouse, and touch interaction handling.
npx @tessl/cli install tessl/npm-react-aria--button@3.14.0@react-aria/button provides React hooks for implementing accessible button components with comprehensive keyboard, mouse, and touch interaction handling. It offers the useButton hook that enables developers to create ARIA-compliant button interfaces across various HTML elements while maintaining consistent focus management, press state handling, and accessibility attributes.
npm install @react-aria/buttonimport { useButton, useToggleButton, useToggleButtonGroup, useToggleButtonGroupItem } from "@react-aria/button";
import { useToggleState } from "@react-stately/toggle";
import { useToggleGroupState } from "@react-stately/toggle";For CommonJS:
const { useButton, useToggleButton, useToggleButtonGroup, useToggleButtonGroupItem } = require("@react-aria/button");
const { useToggleState, useToggleGroupState } = require("@react-stately/toggle");import { useButton, useToggleButton, useToggleButtonGroup, useToggleButtonGroupItem } from "@react-aria/button";
import { useToggleState, useToggleGroupState } from "@react-stately/toggle";
import { useRef } from "react";
// Basic button
function Button(props) {
let ref = useRef<HTMLButtonElement | null>(null);
let { buttonProps, isPressed } = useButton(props, ref);
return (
<button {...buttonProps} ref={ref}>
{props.children}
</button>
);
}
// Toggle button
function ToggleButton(props) {
let ref = useRef<HTMLButtonElement | null>(null);
let state = useToggleState(props);
let { buttonProps, isPressed, isSelected } = useToggleButton(props, state, ref);
return (
<button {...buttonProps} ref={ref} style={{ background: isSelected ? 'blue' : 'gray' }}>
{props.children}
</button>
);
}
// Toggle button group
function ToggleButtonGroup(props) {
let groupRef = useRef<HTMLDivElement | null>(null);
let state = useToggleGroupState(props);
let { groupProps } = useToggleButtonGroup(props, state, groupRef);
return (
<div {...groupProps} ref={groupRef}>
{props.children}
</div>
);
}
// Toggle button group item
function ToggleButtonGroupItem(props) {
let ref = useRef<HTMLButtonElement | null>(null);
let { buttonProps, isPressed, isSelected } = useToggleButtonGroupItem(props, props.state, ref);
return (
<button {...buttonProps} ref={ref} style={{ background: isSelected ? 'blue' : 'gray' }}>
{props.children}
</button>
);
}
// Usage examples
<Button onPress={() => alert('Button pressed!')}>Click me</Button>
<ToggleButton>Toggle me</ToggleButton>@react-aria/button is built around several key components:
useButton provides fundamental button behavior and accessibilityuseToggleButton extends button behavior with selection state managementuseToggleButtonGroup and useToggleButtonGroupItem handle collections of toggle buttonsProvides fundamental button behavior with accessibility, press state management, and support for multiple element types.
function useButton<E extends ElementType>(
props: AriaButtonOptions<E>,
ref: RefObject<Element | null>
): ButtonAria<DOMAttributes>;
interface AriaButtonOptions<E extends ElementType> extends Omit<AriaButtonProps<E>, 'children'> {}
interface ButtonAria<T> {
/** Props for the button element. */
buttonProps: T;
/** Whether the button is currently pressed. */
isPressed: boolean;
}Extends button behavior with selection state management for toggle buttons that maintain on/off states.
function useToggleButton<E extends ElementType>(
props: AriaToggleButtonOptions<E>,
state: ToggleState,
ref: RefObject<Element | null>
): ToggleButtonAria<DOMAttributes>;
interface AriaToggleButtonOptions<E extends ElementType> extends Omit<AriaToggleButtonProps<E>, 'children'> {}
interface ToggleButtonAria<T> extends ButtonAria<T> {
/** Whether the button is selected. */
isSelected: boolean;
/** Whether the button is disabled. */
isDisabled: boolean;
}Manages collections of toggle buttons with proper ARIA semantics, supporting both single and multiple selection modes.
function useToggleButtonGroup(
props: AriaToggleButtonGroupProps,
state: ToggleGroupState,
ref: RefObject<HTMLElement | null>
): ToggleButtonGroupAria;
function useToggleButtonGroupItem<E extends ElementType>(
props: AriaToggleButtonGroupItemOptions<E>,
state: ToggleGroupState,
ref: RefObject<Element | null>
): ToggleButtonAria<DOMAttributes>;
interface AriaToggleButtonGroupProps extends ToggleGroupProps, AriaLabelingProps {
/** The orientation of the toggle button group. @default 'horizontal' */
orientation?: Orientation;
}
interface AriaToggleButtonGroupItemOptions<E extends ElementType> extends Omit<AriaToggleButtonGroupItemProps<E>, 'children'> {
/** An identifier for the item in the selectedKeys of a ToggleButtonGroup. */
id: Key;
}
interface ToggleButtonGroupAria {
/** Props for the toggle button group container. */
groupProps: DOMAttributes;
}import { ElementType, RefObject, ReactNode, JSXElementConstructor, MouseEvent, AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, InputHTMLAttributes } from 'react';
import { AriaLabelingProps, DOMAttributes, FocusableDOMProps, PressEvents, FocusableProps, Key, Orientation } from '@react-types/shared';
import { ToggleState, ToggleGroupState, ToggleGroupProps } from '@react-stately/toggle';
type Selection = 'all' | Set<Key>;
type SelectionMode = 'none' | 'single' | 'multiple';
interface PressEvent {
/** The type of press event being fired. */
type: 'pressstart' | 'pressend' | 'pressup' | 'press';
/** The pointer type that triggered the press event. */
pointerType: 'mouse' | 'pen' | 'touch' | 'keyboard' | 'virtual';
/** The target element of the press event. */
target: Element;
/** Whether the shift keyboard modifier was held during the press event. */
shiftKey: boolean;
/** Whether the ctrl keyboard modifier was held during the press event. */
ctrlKey: boolean;
/** Whether the meta keyboard modifier was held during the press event. */
metaKey: boolean;
/** Whether the alt keyboard modifier was held during the press event. */
altKey: boolean;
}
interface AriaButtonProps<T extends ElementType = 'button'> extends ButtonProps, LinkButtonProps<T>, AriaBaseButtonProps {}
interface ButtonProps extends PressEvents, FocusableProps {
/** Whether the button is disabled. */
isDisabled?: boolean;
/** The content to display in the button. */
children?: ReactNode;
}
interface LinkButtonProps<T extends ElementType = 'button'> extends AriaButtonElementTypeProps<T> {
/** 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;
}
interface AriaButtonElementTypeProps<T extends ElementType = 'button'> {
/** The HTML element or React element used to render the button. @default 'button' */
elementType?: T | JSXElementConstructor<any>;
}
interface AriaBaseButtonProps extends FocusableDOMProps, AriaLabelingProps {
/** Indicates whether the element is disabled to users of assistive technology. */
'aria-disabled'?: boolean | 'true' | 'false';
/** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */
'aria-expanded'?: boolean | 'true' | 'false';
/** Indicates the availability and type of interactive popup element. */
'aria-haspopup'?: boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | 'true' | 'false';
/** Identifies the element (or elements) whose contents or presence are controlled by the current element. */
'aria-controls'?: string;
/** Indicates the current "pressed" state of toggle buttons. */
'aria-pressed'?: boolean | 'true' | 'false' | 'mixed';
/** Indicates whether this element represents the current item within a container or set of related elements. */
'aria-current'?: boolean | 'true' | 'false' | 'page' | 'step' | 'location' | 'date' | 'time';
/** The behavior of the button when used in an HTML form. @default 'button' */
type?: 'button' | 'submit' | 'reset';
/** Whether to prevent focus from moving to the button when pressing it. */
preventFocusOnPress?: boolean;
/** 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;
}
interface AriaToggleButtonProps<T extends ElementType = 'button'> extends ToggleButtonProps, Omit<AriaBaseButtonProps, 'aria-current' | 'form' | 'formAction' | 'formEncType' | 'formMethod' | 'formNoValidate' | 'formTarget' | 'name' | 'value' | 'type'>, AriaButtonElementTypeProps<T> {}
interface ToggleButtonProps extends ButtonProps {
/** Whether the element should be selected (controlled). */
isSelected?: boolean;
/** Whether the element should be selected (uncontrolled). */
defaultSelected?: boolean;
/** Handler that is called when the element's selection state changes. */
onChange?: (isSelected: boolean) => void;
}
// Exported Type Aliases
type AriaButtonOptions<E extends ElementType> = Omit<AriaButtonProps<E>, 'children'>;
type AriaToggleButtonOptions<E extends ElementType> = Omit<AriaToggleButtonProps<E>, 'children'>;
type AriaToggleButtonGroupItemProps<E extends ElementType = 'button'> = Omit<AriaToggleButtonProps<E>, 'id' | 'isSelected' | 'defaultSelected' | 'onChange'> & {
/** An identifier for the item in the selectedKeys of a ToggleButtonGroup. */
id: Key;
};
// Return Interfaces
interface ButtonAria<T> {
/** Props for the button element. */
buttonProps: T;
/** Whether the button is currently pressed. */
isPressed: boolean;
}
interface ToggleButtonAria<T> extends ButtonAria<T> {
/** Whether the button is selected. */
isSelected: boolean;
/** Whether the button is disabled. */
isDisabled: boolean;
}
interface ToggleButtonGroupAria {
/** Props for the toggle button group container. */
groupProps: DOMAttributes;
}
// State Management Interfaces
interface ToggleState {
/** Whether the toggle is selected. */
isSelected: boolean;
/** Sets whether the toggle is selected. */
setSelected(isSelected: boolean): void;
/** Toggles the selection state. */
toggle(): void;
}
interface ToggleGroupState {
/** The keys for the currently selected items. */
selectedKeys: Set<Key>;
/** Whether the collection allows empty selection. */
disallowEmptySelection: boolean;
/** The selection mode for the collection. */
selectionMode: SelectionMode;
/** Whether the collection is disabled. */
isDisabled: boolean;
/** Sets the selected keys. */
setSelected(key: Key, selected: boolean): void;
/** Toggles the selection state of an item. */
toggleKey(key: Key): void;
/** Replaces the selection with only the given key. */
selectKey(key: Key): void;
/** Selects all items in the collection. */
selectAll(): void;
/** Clears the selection. */
clearSelection(): void;
}
interface ToggleGroupProps {
/** The currently selected keys in the collection (controlled). */
selectedKeys?: 'all' | Iterable<Key>;
/** The initial selected keys in the collection (uncontrolled). */
defaultSelectedKeys?: 'all' | Iterable<Key>;
/** Handler that is called when the selection changes. */
onChange?: (keys: Selection) => void;
/** The type of selection that is allowed in the collection. */
selectionMode?: SelectionMode;
/** Whether the collection allows empty selection. */
disallowEmptySelection?: boolean;
}