DEV Community

Alex Spinov
Alex Spinov

Posted on

React Aria Has a Free API — Adobe's Accessible Component Hooks

React Aria is a library of unstyled, accessible hooks from Adobe. It handles keyboard navigation, screen readers, focus management, and internationalization — you handle the styling.

Why React Aria?

  • 100% accessible — WCAG 2.1 AA compliant out of the box
  • Unstyled — hooks, not components — style however you want
  • Internationalization — 30+ languages, RTL, date/number formatting
  • Keyboard/touch — handles all interaction modes correctly

Quick Start

npm install react-aria-components
Enter fullscreen mode Exit fullscreen mode

Pre-Built Components (react-aria-components)

import { Button, TextField, Label, Input, Select, SelectValue, Popover, ListBox, ListBoxItem } from 'react-aria-components';

function MyForm() {
  return (
    <form>
      <TextField>
        <Label>Email</Label>
        <Input type="email" />
      </TextField>

      <Select>
        <Label>Role</Label>
        <Button><SelectValue /></Button>
        <Popover>
          <ListBox>
            <ListBoxItem>Admin</ListBoxItem>
            <ListBoxItem>User</ListBoxItem>
            <ListBoxItem>Guest</ListBoxItem>
          </ListBox>
        </Popover>
      </Select>

      <Button type="submit">Submit</Button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Hooks (Low-Level)

import { useButton } from 'react-aria';
import { useRef } from 'react';

function MyButton(props) {
  const ref = useRef(null);
  const { buttonProps } = useButton(props, ref);

  return (
    <button {...buttonProps} ref={ref} className="my-button">
      {props.children}
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

Dialog/Modal

import { DialogTrigger, Modal, Dialog, Heading } from 'react-aria-components';

function MyDialog() {
  return (
    <DialogTrigger>
      <Button>Open Dialog</Button>
      <Modal>
        <Dialog>
          <Heading slot="title">Confirm</Heading>
          <p>Are you sure?</p>
          <Button slot="close">Cancel</Button>
          <Button>Confirm</Button>
        </Dialog>
      </Modal>
    </DialogTrigger>
  );
}
Enter fullscreen mode Exit fullscreen mode

Table

import { Table, TableHeader, Column, TableBody, Row, Cell } from 'react-aria-components';

function UserTable({ users }) {
  return (
    <Table aria-label="Users" selectionMode="multiple">
      <TableHeader>
        <Column isRowHeader>Name</Column>
        <Column>Email</Column>
        <Column>Role</Column>
      </TableHeader>
      <TableBody>
        {users.map(user => (
          <Row key={user.id}>
            <Cell>{user.name}</Cell>
            <Cell>{user.email}</Cell>
            <Cell>{user.role}</Cell>
          </Row>
        ))}
      </TableBody>
    </Table>
  );
}
Enter fullscreen mode Exit fullscreen mode

Date Picker

import { DatePicker, Label, Group, DateInput, DateSegment, Button, Popover, Dialog, Calendar, CalendarGrid, CalendarCell } from 'react-aria-components';

function MyDatePicker() {
  return (
    <DatePicker>
      <Label>Date</Label>
      <Group>
        <DateInput>{(segment) => <DateSegment segment={segment} />}</DateInput>
        <Button>Open</Button>
      </Group>
      <Popover>
        <Dialog>
          <Calendar>
            <CalendarGrid>
              {(date) => <CalendarCell date={date} />}
            </CalendarGrid>
          </Calendar>
        </Dialog>
      </Popover>
    </DatePicker>
  );
}
Enter fullscreen mode Exit fullscreen mode

Building accessible data apps? Check out my Apify actors for web scraping, or email spinov001@gmail.com for accessible React solutions.

React Aria, Radix UI, or Headless UI — which accessible library do you use? Share below!

Top comments (0)