Ariakit logo

Ariakit

A low-level, unstyled component library for building accessible web applications with complete design freedom.

npm install ariakit
8.5K35.4K/weekv2.0.0-next.441.46 MBMIT112 issues
Last updated: 2023-04-11
Star history chart for ariakit/ariakit

TL;DR

A library of unstyled, primitive components (formerly Reakit) that handle WAI-ARIA roles, focus management, and keyboard interactions, allowing you to build custom design systems without reinventing the wheel.

Designed to be headless and composable, it works seamlessly with any styling solution, including Tailwind CSS, CSS-in-JS, or plain CSS.

Why Ariakit?

Ariakit (formerly Reakit) addresses the hardest part of building custom UI: Accessibility (a11y) and Behavior. Building a modal or dropdown that visually looks correct is easy; building one that manages focus traps, handles Escape keys, supports screen readers, and works across devices is incredibly difficult. Ariakit provides these behaviors as "headless" components, meaning they render HTML but contain no visual styles.

  • Headless Architecture: Components ship with zero CSS. You have total control over the class names, DOM structure, and styling implementation.
  • WAI-ARIA Compliant: Out-of-the-box support for WAI-ARIA patterns. It automatically manages complex attributes like aria-expanded, aria-controls, and aria-activedescendant.
  • Focus Management: Handles difficult interactions like focus trapping in modals, roving tabindex in menus, and focus restoration upon closing.
  • Composition Model: Uses a flexible composition model (Components as props or hooks) that allows you to merge behavior onto any element.
  • Tiny Bundle Size: Modular architecture ensures you only bundle the code for the primitives you actually use.

Code Snippet

Ariakit components are unstyled. In this example, className is used to apply styles (e.g., via CSS Modules or Tailwind), while Ariakit handles the state (open) and the accessibility logic (rendering the backdrop, trapping focus).

import { useState } from "react";
import { Button, Dialog, DialogHeading, DialogDescription } from "@ariakit/react";

export default function ExampleDialog() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)} className="btn-primary">
        Open Modal
      </Button>
      
      <Dialog 
        open={open} 
        onClose={() => setOpen(false)} 
        className="dialog-content"
        backdrop={<div className="dialog-backdrop" />}
      >
        <DialogHeading className="text-xl font-bold">
          Accessibility Solved
        </DialogHeading>
        
        <DialogDescription className="mt-2 text-gray-600">
          This dialog automatically traps focus within it while open 
          and restores focus to the trigger button when closed.
        </DialogDescription>
        
        <div className="mt-4 flex justify-end">
          <Button onClick={() => setOpen(false)} className="btn-secondary">
            Dismiss
          </Button>
        </div>
      </Dialog>
    </>
  );
}

Pros and Cons

No library is perfect; understanding the trade-offs is key to selecting the right tool.

Pros

  • Total Styling Freedom: Since there are no default styles to override, you never have to fight !important rules or specificity wars.
  • Accessibility Robustness: It handles edge cases in screen reader interaction that most custom implementations miss.
  • Framework Agnostic Logic: While the React package is popular, the core logic is separated, making the patterns stable and well-tested.

Cons

  • No "Out of the Box" UI: You cannot just "drop it in" and have a pretty app. It requires you to be a designer (or have a design system) to look good.
  • Setup Time: Implementing a simple dropdown requires more boilerplate code (styling, positioning) compared to a pre-styled library like MUI.
  • Documentation Density: Because it exposes low-level primitives, the API surface can be vast and sometimes overwhelming for simple tasks.

Comparison with Other Headless Libraries

The table below outlines the positioning differences between Ariakit and other headless solutions:

LibraryDesign PhilosophyBest ForPain Points
AriakitMaximum Flexibility
Low-level primitives with a focus on composition and generic HTML elements.
Design Systems
Teams building a reusable component library from scratch.
Boilerplate
Requires more setup to connect styles and state than opinionated alternatives.
Radix UIComponent-First
Polished, unstyled components with a slightly more rigid API structure.
Modern Apps
Next.js apps needing high-quality, accessible primitives quickly.
DOM Structure
Sometimes injects extra wrapper divs or requires specific hierarchy.
Headless UITailwind Integrated
Built by the Tailwind team, optimized for utility classes.
Tailwind Projects
Simple integrations with Tailwind CSS.
Fewer Components
Smaller selection of components compared to Ariakit or Radix.

Verdict: When to Adopt

Choose Ariakit if you are tasked with building a Design System for your organization and need absolute control over the DOM and CSS while ensuring WCAG compliance. It is the tool for "builders" who want to own the pixel-perfect rendering but don't want to maintain the complex JavaScript logic required for accessible interactions.