CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-aria

Comprehensive library of unstyled React hooks providing accessible UI primitives with full WAI-ARIA compliance and internationalization support.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

tags.mddocs/

Tags

Tag components for displaying and managing collections of labels, categories, or metadata with full accessibility support including keyboard navigation and screen reader announcements.

Capabilities

Tag

Provides individual tag behavior with optional dismiss functionality and keyboard navigation.

/**
 * Provides tag behavior and accessibility
 * @param props - Tag configuration options
 * @param state - Tag state from useTagState
 * @param ref - Ref to the tag element
 * @returns Tag props and state
 */
function useTag(props: AriaTagProps, state: TagState, ref: RefObject<Element>): TagAria;

interface AriaTagProps {
  /** Tag content/label */
  children: ReactNode;
  /** Whether the tag can be removed */
  isDismissible?: boolean;
  /** Whether the tag is disabled */
  isDisabled?: boolean;
  /** Whether the tag is selected (for selectable tags) */
  isSelected?: boolean;
  /** Handler called when the tag is dismissed */
  onDismiss?: () => void;
  /** Handler called when the tag is selected */
  onSelect?: () => void;
  /** Text content of the tag for accessibility */
  textValue?: string;
  /** ARIA label for the dismiss button */
  dismissLabel?: string;
}

interface TagAria {
  /** Props to spread on the tag element */
  tagProps: DOMAttributes<Element>;
  /** Props for the dismiss button (if dismissible) */
  dismissButtonProps: DOMAttributes<Element>;
  /** Whether the tag is currently focused */
  isFocused: boolean;
  /** Whether the tag is currently hovered */
  isHovered: boolean;
}

Usage Example:

import { useTag } from "react-aria";
import { useTagState } from "react-stately";

function Tag(props) {
  let state = useTagState(props);
  let ref = useRef();
  let { tagProps, dismissButtonProps, isFocused } = useTag(props, state, ref);

  return (
    <div
      {...tagProps}
      ref={ref}
      className={`tag ${isFocused ? 'focused' : ''} ${props.isSelected ? 'selected' : ''}`}
    >
      <span className="tag-content">{props.children}</span>
      {props.isDismissible && (
        <button {...dismissButtonProps} className="tag-dismiss">
          ×
        </button>
      )}
    </div>
  );
}

Tag Group

Manages a collection of tags with keyboard navigation, selection state, and batch operations.

/**
 * Provides tag group behavior for managing collections of tags
 * @param props - Tag group configuration
 * @param state - Tag group state from useTagGroupState
 * @param ref - Ref to the tag group element
 * @returns Tag group props and utilities
 */
function useTagGroup(props: AriaTagGroupProps, state: TagGroupState, ref: RefObject<Element>): TagGroupAria;

interface AriaTagGroupProps {
  /** Collection of tag items */
  items?: Iterable<TagItem>;
  /** Whether multiple tags can be selected */
  selectionMode?: 'none' | 'single' | 'multiple';
  /** Currently selected tag keys */
  selectedKeys?: Iterable<Key>;
  /** Default selected keys (uncontrolled) */
  defaultSelectedKeys?: Iterable<Key>;
  /** Handler called when selection changes */
  onSelectionChange?: (keys: Set<Key>) => void;
  /** Handler called when a tag is dismissed */
  onDismiss?: (key: Key) => void;
  /** Whether the tag group is disabled */
  isDisabled?: boolean;
  /** Whether tags are read-only */
  isReadOnly?: boolean;
  /** Maximum number of tags to display */
  maxTags?: number;
  /** Label for the tag group */
  label?: ReactNode;
  /** Description for the tag group */
  description?: ReactNode;
  /** Error message for validation */
  errorMessage?: ReactNode;
}

interface TagGroupAria {
  /** Props to spread on the tag group container */
  tagGroupProps: DOMAttributes<Element>;
  /** Props for the group label */
  labelProps: DOMAttributes<Element>;
  /** Props for the description */
  descriptionProps: DOMAttributes<Element>;
  /** Props for the error message */
  errorMessageProps: DOMAttributes<Element>;
}

Usage Example:

import { useTagGroup } from "react-aria";
import { useTagGroupState } from "react-stately";

function TagGroup(props) {
  let state = useTagGroupState(props);
  let ref = useRef();
  let { tagGroupProps, labelProps, descriptionProps } = useTagGroup(props, state, ref);

  return (
    <div {...tagGroupProps} ref={ref} className="tag-group">
      {props.label && (
        <label {...labelProps} className="tag-group-label">
          {props.label}
        </label>
      )}
      <div className="tag-list">
        {state.collection.map((item) => (
          <Tag
            key={item.key}
            item={item}
            state={state}
            isDismissible={!props.isReadOnly}
            isSelected={state.selectionManager.isSelected(item.key)}
            onDismiss={() => props.onDismiss?.(item.key)}
          />
        ))}
      </div>
      {props.description && (
        <div {...descriptionProps} className="tag-group-description">
          {props.description}
        </div>
      )}
    </div>
  );
}

Types

interface TagState {
  /** Whether the tag is selected */
  isSelected: boolean;
  /** Whether the tag is focused */
  isFocused: boolean;
  /** Whether the tag is hovered */
  isHovered: boolean;
  /** Whether the tag can be dismissed */
  isDismissible: boolean;
}

interface TagGroupState {
  /** Collection of tag items */
  collection: Collection<TagItem>;
  /** Selection manager for the tag group */
  selectionManager: SelectionManager;
  /** Whether the tag group is disabled */
  isDisabled: boolean;
  /** Add a new tag to the group */
  addTag: (tag: TagItem) => void;
  /** Remove a tag from the group by key */
  removeTag: (key: Key) => void;
  /** Clear all tags */
  clear: () => void;
}

interface TagItem {
  /** Unique identifier for the tag */
  key: Key;
  /** Tag content */
  content: ReactNode;
  /** Text representation for accessibility */
  textValue: string;
  /** Whether this tag is dismissible */
  isDismissible?: boolean;
  /** Whether this tag is disabled */
  isDisabled?: boolean;
}

Install with Tessl CLI

npx tessl i tessl/npm-react-aria

docs

date-time.md

drag-drop.md

focus-management.md

form-controls.md

index.md

interactions.md

internationalization.md

layout-navigation.md

overlays-modals.md

selection-controls.md

tags.md

toast-notifications.md

utilities.md

tile.json