CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-aria--button

React hooks for implementing accessible button components with comprehensive keyboard, mouse, and touch interaction handling.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

toggle-button.mddocs/

Toggle Button Functionality

Extends button behavior with selection state management for toggle buttons that maintain on/off states. The useToggleButton hook builds on useButton to provide accessible toggle functionality with proper ARIA pressed states.

Capabilities

useToggleButton Hook

Creates accessible toggle button behavior with selection state management.

/**
 * Provides the behavior and accessibility implementation for a toggle button component.
 * ToggleButtons allow users to toggle a selection on or off, for example switching between two states or modes.
 */
function useToggleButton(props: AriaToggleButtonOptions<'button'>, state: ToggleState, ref: RefObject<HTMLButtonElement | null>): ToggleButtonAria<ButtonHTMLAttributes<HTMLButtonElement>>;
function useToggleButton(props: AriaToggleButtonOptions<'a'>, state: ToggleState, ref: RefObject<HTMLAnchorElement | null>): ToggleButtonAria<AnchorHTMLAttributes<HTMLAnchorElement>>;
function useToggleButton(props: AriaToggleButtonOptions<'div'>, state: ToggleState, ref: RefObject<HTMLDivElement | null>): ToggleButtonAria<HTMLAttributes<HTMLDivElement>>;
function useToggleButton(props: AriaToggleButtonOptions<'input'>, state: ToggleState, ref: RefObject<HTMLInputElement | null>): ToggleButtonAria<InputHTMLAttributes<HTMLInputElement>>;
function useToggleButton(props: AriaToggleButtonOptions<'span'>, state: ToggleState, ref: RefObject<HTMLSpanElement | null>): ToggleButtonAria<HTMLAttributes<HTMLSpanElement>>;
function useToggleButton(props: AriaToggleButtonOptions<ElementType>, state: ToggleState, ref: RefObject<Element | null>): ToggleButtonAria<DOMAttributes>;

Usage Examples:

import { useToggleButton } from "@react-aria/button";
import { useToggleState } from "@react-stately/toggle";
import { useRef, useState } from "react";

// Basic toggle button
function ToggleButton(props) {
  let ref = useRef<HTMLButtonElement | null>(null);
  let state = useToggleState(props);
  let { buttonProps, isPressed, isSelected, isDisabled } = useToggleButton(props, state, ref);

  return (
    <button
      {...buttonProps}
      style={{
        background: isPressed
          ? (isSelected ? 'darkgreen' : 'gray')
          : (isSelected ? 'green' : 'lightgray'),
        color: isSelected ? 'white' : 'black',
        padding: 10,
        border: 'none'
      }}
      ref={ref}>
      {props.children}
    </button>
  );
}

// Controlled toggle button
function ControlledToggleButton() {
  let [isSelected, setSelected] = useState(false);

  return (
    <ToggleButton
      isSelected={isSelected}
      onChange={setSelected}
      aria-label="Toggle favorite">
      ★
    </ToggleButton>
  );
}

// Custom element toggle button
function CustomToggleButton(props) {
  let ref = useRef<HTMLDivElement | null>(null);
  let state = useToggleState(props);
  let { buttonProps, isSelected, isPressed } = useToggleButton({
    ...props,
    elementType: 'div'
  }, state, ref);

  return (
    <div
      {...buttonProps}
      style={{
        background: isSelected ? '#007acc' : '#f0f0f0',
        color: isSelected ? 'white' : 'black',
        padding: '8px 16px',
        border: isPressed ? '2px solid #005a9e' : '2px solid transparent',
        borderRadius: 4,
        cursor: 'pointer',
        userSelect: 'none'
      }}
      ref={ref}>
      {props.children}
    </div>
  );
}

Toggle Button Options Interface

Configuration options for toggle button behavior.

interface AriaToggleButtonOptions<E extends ElementType> extends Omit<AriaToggleButtonProps<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;
  /** 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;
  /** 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. */
  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. */
  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;
}

Toggle Button Return Interface

Return value from the useToggleButton hook containing props and state.

interface ToggleButtonAria<T> extends ButtonAria<T> {
  /** Whether the button is selected. */
  isSelected: boolean;
  /** Whether the button is disabled. */
  isDisabled: boolean;
}

Toggle State Interface

State management interface for toggle buttons (from @react-stately/toggle).

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;
}

State Management

Toggle buttons require state management via the useToggleState hook from @react-stately/toggle:

import { useToggleState } from "@react-stately/toggle";

// Uncontrolled (default selection)
let state = useToggleState({ defaultSelected: false });

// Controlled 
let state = useToggleState({ 
  isSelected: isSelected,
  onChange: setSelected 
});

Element Type Support

Like useButton, useToggleButton supports multiple HTML element types:

Native Button Element (elementType: 'button')

  • Standard button behavior with toggle state
  • aria-pressed attribute for screen readers
  • No form-related props (removed from toggle button interface)

Anchor Element (elementType: 'a')

  • ARIA role="button" with aria-pressed
  • No href support (not applicable for toggle buttons)
  • Disabled state via aria-disabled

Generic Elements (elementType: 'div' | 'span')

  • ARIA role="button" with aria-pressed
  • Full keyboard support
  • Visual press and selection states

Input Element (elementType: 'input')

  • ARIA role="button" with aria-pressed
  • Native disabled attribute support
  • Input type support limited

Accessibility Features

  • ARIA Pressed State: Automatic aria-pressed attribute management
  • Screen Reader Support: Clear selection state announcement
  • Keyboard Support: Space and Enter key toggle functionality
  • Focus Management: Proper focus behavior across element types
  • State Changes: Accessible state change notifications
  • Visual Indicators: Press and selection state support for styling

Selection State Handling

The toggle button automatically manages:

  • Press Events: Integrates with button press handling
  • State Synchronization: Keeps UI in sync with state
  • Change Events: Fires onChange when selection state changes
  • ARIA Attributes: Updates aria-pressed based on selection
  • Default State: Supports both controlled and uncontrolled patterns

Integration with useButton

useToggleButton internally uses useButton and extends it with:

  • Selection state management
  • Toggle functionality on press
  • ARIA pressed state attributes
  • State synchronization
  • onChange event integration

All useButton functionality (press states, element types, accessibility) is preserved and enhanced with toggle capabilities.

Install with Tessl CLI

npx tessl i tessl/npm-react-aria--button

docs

core-button.md

index.md

toggle-button-groups.md

toggle-button.md

tile.json