React

React Ariaとは?React Aria Componentsの使い方・Tailwind連携【v1.22対応】

React Ariaとは?React Aria Componentsの使い方・Tailwind連携【v1.22対応】

React Ariaは、Adobeが開発しているReact向けのアクセシビリティ実装ライブラリです。キーボード操作、フォーカス管理、スクリーンリーダー向けのARIA属性、日付や数値の国際化といった「自作すると壊れやすい振る舞い」を引き受け、見た目は一切持ちません。2025年12月に公式サイトがreact-aria.adobe.comへ移り、2026年は毎月のように新しいコンポーネントが追加されました。この記事では、2026年10月時点の最新版(react-aria-components 1.22.1)を前提に、パッケージ構成、導入手順、実際に出力されるHTML、Tailwind連携、AIコーディング向けの提供物、React Native対応の実態までを整理します。

まとめ:React Ariaの要点

  • React Ariaはスタイルを持たない(unstyled)アクセシビリティ実装ライブラリ。HTMLのaria-*属性(WAI-ARIA)そのものではなく、それを正しく付けて操作まで実装する道具。
  • 使うのは基本的にreact-aria-components(2026年10月9日公開の1.22.1)。独自のDOM構造が必要な部品だけ、低レベルのフックreact-aria(3.53.1)に降りる。
  • 2026年4月の1.17.0で個別パッケージ(@react-aria/buttonなど)はモノパッケージへ統合され、react-aria-components/Buttonのようなサブパスimportが使えるようになった。
  • Tailwind CSS v4ではtailwindcss-react-aria-components 2.x を@pluginで読み込み、pressed:やselected:で状態別にスタイルを書く。
  • 公式がAgent Skills・MCPサーバー(@react-aria/mcp)・llms.txtを提供しており、AIコーディングツールに最新のAPIを渡せる。
  • Adobe公式のドキュメントとテストはWeb(DOM)向け。React Nativeでは、コンポーネント版はreact-dom依存のため使えない前提で考える。

React Ariaとは:Adobeが作るアクセシビリティの振る舞いライブラリ

React Ariaは、Adobeのモノレポadobe/react-spectrumで開発されているOSSです。ボタンやメニュー、日付ピッカーなどのUI部品について、操作の振る舞いとアクセシビリティだけを提供し、色・余白・レイアウトは開発者が決めます。公式の品質ガイドは、WAI-ARIAとARIA Authoring Practicesに従ってロールと属性を付け、キーボードとポインター操作、フォーカス、読み上げ通知を扱うと説明しています。

WAI-ARIA(HTML属性)との違い

「aria」はWAI-ARIA(Accessible Rich Internet Applications)に由来する語で、読み方は「アリア」です。WAI-ARIAはW3Cの仕様で、role="switch"やaria-expanded="true"のようなHTML要素に付ける属性を定めています。属性を付けたうえで、矢印キーでの移動やフォーカスの戻し先まで実装するのは開発者の仕事です。React Ariaは、その属性付与と操作ロジックをまとめて肩代わりするライブラリです。属性そのものの意味や使い分けはWAI-ARIAとは?role・aria属性の使い方とネイティブHTMLを優先すべき理由で解説しています。

テスト対象のスクリーンリーダーと国際化の範囲

公式が動作確認の対象に挙げているのは、macOSのVoiceOver(SafariとChrome)、WindowsのJAWSとNVDA(FirefoxとChrome)、iOSのVoiceOver、AndroidのTalkBack(Chrome)です。国際化では30以上の言語の文言を内蔵し、13のカレンダー方式と右から左に書く言語のキーボード操作に対応します。日本語環境で効くのは日付の並び順で、同じDateFieldをロケールja-JPで描画すると「2026/10/26」、en-USでは「10/26/2026」の順に入力欄が並びました(react-dom/serverでの描画結果)。

React Spectrumとの関係とパッケージ構成

React Ariaは、AdobeのデザインシステムReact Spectrumの土台として作られています。2025年12月16日の1.14.0と同時に、React Aria Componentsの上に構築されたSpectrum 2(@react-spectrum/s2)の安定版も公開されました。npmで公開されている主なパッケージと、2026年10月26日時点の版は次のとおりです。

パッケージ 役割 最新版 スタイル React
react-aria-components 高レベルの部品 1.22.1 なし 16.8〜19
react-aria 低レベルのフック 3.53.1 なし 16.8〜19
react-stately 状態管理のフック 3.51.0 なし 16.8〜19
@react-spectrum/s2 Adobeデザインの完成品 1.8.2 あり 19のみ

版とpeerDependenciesはnpmのreact-aria-componentsなどのレジストリ情報で確認しました。React 18以前のプロジェクトでもReact Aria Componentsは使えますが、Spectrum 2はReact 19が前提です。自社のデザインで作るならReact Aria Components、Adobeの見た目をそのまま使うならSpectrum 2、という分け方になります。

react-ariaとreact-aria-componentsの使い分け

迷ったらreact-aria-componentsを選びます。公式ドキュメントのコンポーネント一覧には2026年10月26日時点で55項目が並び、状態はdata属性で外に出るので、多くのプロジェクトはフックを直接触らずに済みます。フックへ降りる理由になるのは、提供部品の構造では組めない独自要素に振る舞いだけを付けたい場合と、既存デザインシステムの内部実装に差し込みたい場合です。

「低レベルの方が柔軟そう」という理由でフックから始めるのは避けた方がよいです。フックはref経由で要素にpropsを展開する使い方で、部品なら自動で守られる部分を自分で守る必要があります。実際、useButtonを<div>に当てるときにelementType: 'div'を渡し忘れると、出力は<div type="button" tabindex="0">になり、role="button"が付きません。スクリーンリーダーはこれをボタンとして読み上げないので、見た目は動くのにアクセシビリティだけが壊れた部品になります。elementType: 'div'を渡すとrole="button"が付きます(refの扱いはuseRefの使い方|DOM参照・値の保持とuseStateとの違いを参照)。

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

function DivButton(props) {
  let ref = useRef(null);
  // div や span に当てるときは elementType が必須
  let {buttonProps} = useButton({...props, elementType: 'div'}, ref);
  return <div {...buttonProps} ref={ref}>{props.children}</div>;
}

React Aria Componentsの導入・移行・Next.js設定

npm installとサブパスimport

導入はパッケージ1つです。React 19と一緒に入れたプロジェクトでnpm ls --allを数えると16パッケージで、React本体の3つ(react・react-dom・scheduler)を除くと13でした。

npm install react-aria-components

1.17.0のリリースノートによると、2026年4月14日公開のこの版で依存パッケージが90%減り、部品ごとのサブパスimportが加わりました。react-aria-components/MenuからはMenu・MenuItem・Popoverなど一緒に使う子部品がまとめて読み込めます。公式ドキュメントのコード例もサブパスで書かれるようになりましたが、従来どおりパッケージ名だけのimportでも動きます。

import {Button} from 'react-aria-components/Button';
import {Menu, MenuItem, Popover} from 'react-aria-components/Menu';

旧@react-aria/*パッケージからの移行

2025年以前の記事やAIが生成したサンプルには、@react-aria/buttonのような個別パッケージを入れる手順が残っています。1.17.0以降、個別パッケージはモノパッケージを再エクスポートする薄い殻になりました(@react-aria/button 3.15.1の依存はreact-ariaと@swc/helpersの2つだけ)。動きはしますが新しいexportは追加されないため、公式のcodemodで置き換えます。

npx @react-spectrum/codemods use-monopackages --path ./src
npx @react-spectrum/codemods use-subpaths --path ./src

手元で試すと、import {useButton} from '@react-aria/button'はuse-monopackagesでfrom "react-aria"に、続けてuse-subpathsでfrom 'react-aria/useButton'に書き換わりました(codemods 1.2.10)。node_modulesに旧パッケージが入っていない状態で実行すると「None of the index files for the selected packages exist.」と出て1件も変わらないので、npm installを済ませてから流します。

注意点が1つあります。これまでモノパッケージ経由で個別パッケージが自動的に入っていたため、package.jsonに書かずに@react-aria/*をimportしていたコードは、更新後にモジュールが見つからず落ちます。webpack 4やJest 28未満への対応は当面残るものの、将来のメジャー版で切ると予告されています。

Next.js App Routerで使う設定

React Aria Componentsの部品はクライアントで状態を持つため、"use client"を付けたファイルから使います。1.22.1のパッケージを開くと、サブパスのエントリ83本のうち71本がclient-onlyをimportしており、パッケージ名だけのメインエントリも同じでした。client-onlyはServer Componentの条件(react-server)で読み込まれると例外を投げる目印のパッケージです。例外はI18nProviderなどの12本で、だからサーバー側のレイアウトでもreact-aria-components/I18nProviderのisRTLは使えます。メインエントリからisRTLをimportすると、この区別が効きません。

公式のフレームワーク設定ガイドが求めているのは、サーバーとクライアントでロケールを一致させることです。ルートレイアウトでlangとdirを決め、クライアント側のI18nProviderに同じ値を渡します。

// app/layout.tsx
import {headers} from 'next/headers';
import {isRTL} from 'react-aria-components/I18nProvider';
import {ClientProviders} from './provider';

export default async function RootLayout({children}: {children: import('react').ReactNode}) {
  const acceptLanguage = (await headers()).get('accept-language');
  const lang = acceptLanguage?.split(/[,;]/)[0] || 'ja-JP';
  return (
    <html lang={lang} dir={isRTL(lang) ? 'rtl' : 'ltr'}>
      <body><ClientProviders lang={lang}>{children}</ClientProviders></body>
    </html>
  );
}

// app/provider.tsx
"use client";
import {I18nProvider} from 'react-aria-components/I18nProvider';

export function ClientProviders({lang, children}: {lang: string; children: import('react').ReactNode}) {
  return <I18nProvider locale={lang}>{children}</I18nProvider>;
}

30以上の言語の文言はそのままだとバンドルに入るため、対応言語が日本語と英語だけなら@react-aria/optimize-locales-pluginで削れます。Next.jsのTurbopack設定に組み込む場合は、Next.js 15.4以降が必要です。

主要コンポーネントの実装例と出力されるHTML

Button・Checkbox・Switchの実装と出力HTML

各部品は操作ロジックを備えていますが、ラベル、状態を示す見た目、フォーカス表示は実装側で整えます。クリックはonClickではなくonPressで受けます。マウス・タッチ・キーボードの押下を同じイベントに揃えるためのReact Aria独自のpropです。

import {Button} from 'react-aria-components/Button';
import {Checkbox} from 'react-aria-components/Checkbox';
import {Switch} from 'react-aria-components/Switch';

export function Settings() {
  return (
    <>
      <Checkbox defaultSelected>同意する</Checkbox>
      <Switch>通知</Switch>
      <Button onPress={() => alert('保存ボタンが押されました')}>保存</Button>
    </>
  );
}

上の3部品と後述のSliderをreact-dom/serverで描画した結果を、次の表にまとめます。

部品 外側の要素 操作を受ける要素 状態の出し方
Button button type=”button” 同じbutton isDisabledでdisabled属性とdata-disabled
Checkbox label 視覚的に隠したinput type=”checkbox” labelにdata-selected
Switch label 隠したinput type=”checkbox” role=”switch” labelにdata-selected
Slider div role=”group” 隠したinput type=”range” data-orientation

CheckboxとSwitchがdivではなくネイティブのinputを中に持っている点が重要です。フォーム送信やブラウザの読み上げはネイティブ要素の挙動に乗り、見た目は外側のlabelに付くdata属性で切り替えます。テストでgetByRole('switch')が拾うのも、この隠れたinputです。

Sliderの子部品構成と出力HTML

Sliderのように内部が複数要素でできている部品は、子部品を組み合わせて構造を自分で決めます。SliderOutputは現在値を<output>要素で表示します。

import {Slider, SliderTrack, SliderThumb, SliderOutput} from 'react-aria-components/Slider';
import {Label} from 'react-aria-components/Label';

<Slider defaultValue={30}>
  <Label>音量</Label>
  <SliderOutput />
  <SliderTrack><SliderThumb /></SliderTrack>
</Slider>

つまみ(SliderThumb)の中にはinput type="range"が隠れていて、aria-valuetextに「30」が入ります。矢印キーでの増減はこのinputが受けます。

スタイリング:data属性・render props・Tailwindプラグイン

data属性とrender propsによる状態別スタイリング

React Aria Componentsは、部品の状態をdata属性で外に出します。独自のclassNameを指定しなければ、クラス名react-aria-部品名も付きます(指定すると置き換わります)。data-hoveredやdata-pressedはCSSの:hover・:activeに近い状態です。入力方法の違いはReact Ariaが吸収していて、たとえばdata-hoveredはタッチ端末では付かないため、タップした後にホバーの見た目が残りません。状態ごとにクラスを切り替えたいときは、classNameに関数を渡すrender propsも使えます。

.react-aria-Button[data-pressed] { background: #005b9f; }
.react-aria-Switch[data-selected] .indicator { transform: translateX(100%); }

Tailwind CSSとtailwindcss-react-aria-components

Tailwindではdata-[selected]:bg-blue-400のようにdata属性の修飾子で書けますが、公式プラグインを入れるとdata-を省いたselected:・pressed:で書け、VS Codeの補完も効きます。公式のスタイリングガイドでは、Tailwind v4ならプラグインの2.x(最新2.2.0)をCSSで読み込み、v3なら1.x をtailwind.config.jsに入れるよう分けています。

npm install tailwindcss-react-aria-components

/* app.css(Tailwind v4) */
@import "tailwindcss";
@plugin "tailwindcss-react-aria-components";
<Button className="bg-blue-600 pressed:bg-blue-800 disabled:opacity-50">保存</Button>
<Tabs className="orientation-vertical:flex-row">...</Tabs>

値を持つ状態はorientation-vertical:のように「名前-値」で書きます。既定ではプレフィックスが付かず、disabled:はReact Ariaのdata-disabledとネイティブの:disabledの両方に当たるCSSを生成します。既存のTailwindクラスと名前がぶつかるなら@plugin "tailwindcss-react-aria-components" { prefix: rac };でrac-を付けられます。状態の組み合わせが増えてクラスが長くなる場合は、Tailwind Variants(tv)の使い方で整理すると保守しやすくなります。

render propによるDOM要素の差し替えと制約

2026年2月4日の1.15.0から、全部品にrender propが付きました。Next.jsのLinkやアニメーションライブラリの要素に差し替える用途です。関数は描画すべきDOM propsとisPressedなどの状態を受け取ります。

import {Button} from 'react-aria-components/Button';
import {motion} from 'motion/react';

<Button render={(domProps, {isPressed}) => (
  <motion.button {...domProps} animate={{scale: isPressed ? 0.9 : 1}} />
)}>押す</Button>

公式のカスタマイズガイドは、想定と同じ要素型を返すこと、ルート要素を1つにすること、受け取ったpropsを必ず渡すことの3点を守るよう求めています。Buttonのrenderで<a>を返すと、出力は<a type="button" href="...">という、Buttonが想定するbutton要素とは異なる出力になりました。リンクが欲しいならLink部品を使います。

直近1年のリリースで増えた機能

react-aria-componentsは1.14.0から1.22.0まで、ほぼ月1回のペースでマイナー版が出ています。公式のリリース一覧から主な変更を抜き出すと次のとおりです。

版 公開日 主な変更
1.14.0 2025-12-16 新ドキュメントサイト、Spectrum 2安定版
1.15.0 2026-02-04 render prop、Agent Skills
1.16.0 2026-03-03 ComboBoxの複数選択、Treeのセクション
1.17.0 2026-04-14 依存90%削減、サブパスimport、Tableの展開行
1.18.0 2026-05-28 Tableのフッター、SliderFill
1.19.0 2026-06-18 GridList・Tree内の入力欄、Autocomplete改善
1.20.0 2026-07-31 PreviewTrigger、TokenField(alpha)
1.21.0 2026-09-01 NavigationTree、Menuの非同期読み込み
1.22.0 2026-10-08 Sheet、Turbopackでのロケール最適化

公開日は公式リリースノートの記載日です。アプリ開発で効くのは、サイドバー用のNavigationTreeと、スマートフォンの下から引き出すトレイを作るSheetです。公式ブログによると、Sheetのスワイプとアニメーションは、CSSのスクロールスナップとビュータイムラインで実装されています。TokenFieldはalphaで、1.21.0ではcaretPositionがselectedRangeに置き換わる変更が入りました。alphaの部品は版をまたいでAPIが変わる前提で、版を固定して使います。

AIコーディングで使う:Agent Skills・MCPサーバー・llms.txt

AIの学習データには統合前のドキュメントも含まれるため、生成されたコードに@react-aria/buttonのような旧importが出てくることがあります。React Ariaは公式のAI向けページで、最新のドキュメントをAIツールへ渡す方法を4つ用意しています。

  • Agent Skills:npx skills add https://react-aria.adobe.comで、Claude CodeなどのAIコーディングツールにReact Ariaのスキルを入れる。
  • MCPサーバー:npmの@react-aria/mcp(最新1.2.1)。Claude Codeならclaude mcp add react-aria npx @react-aria/mcp@latestで追加でき、Cursor・VS Code・Codex・Gemini CLI向けの設定例も公式にある。
  • Markdown版ドキュメント:各ページのURL末尾に.mdを付けるとMarkdownで取得できる。各ページの「Copy for LLM」ボタンも同じ内容をコピーする。
  • llms.txt:Markdown版ページの一覧。

AIにコードを生成させる場合は、MCPサーバーかAgent Skillsで現行ドキュメントを参照させ、生成後にimportとpropを検証します。どちらも入れられない環境では、使う部品のページの.mdを貼り付けて、現行のimportとpropを参照させます。

React NativeにおけるReact Ariaの対応範囲

Adobeの公式ドキュメントはWeb(DOM)を対象にしていて、React Nativeでの使い方は案内していません。2024年1月9日にGitHubのDiscussionsで同じ質問が出た際、メンテナーは「フックは動くはずだが、コンポーネントはreact-domへのさまざまな依存があるため動く見込みは低い」と答えています。1.22.0の変更履歴にはReact NativeでuseControlledStateのearly effectを有効にする変更も入っていますが、公式のテスト対象にReact Nativeは含まれていません。react-aria-componentsはWeb専用、フックをReact Nativeで使うなら自分で動作を確かめる前提、と考えるのが安全です。

「react native aria」で見つかるreact-native-ariaは、gluestackのリポジトリで開発されていた別プロジェクトです。GitHubのリポジトリは2023年12月11日にアーカイブされ、npmのreact-native-aria本体も2022年5月の0.2.3から更新されていません。React Nativeでアクセシブルな部品が必要なら、gluestack-uiのようにReact Nativeを対象にしたUIライブラリを使います。gluestack-ui v5のコア(@gluestack-ui/core 5.0.15)は、Adobeの@react-aria/*と@react-stately/*の個別パッケージを依存に持つ作りです。

ほかのヘッドレスUIとの比較と選び方

ライブラリ 提供元 要素の差し替え 向く場面
React Aria Adobe render prop 国際化・日付・表を含む大規模UI
Headless UI Tailwind Labs as prop 部品の少ないTailwind中心のUI
Base UI MUIのチーム render prop shadcn/uiの既定構成
Radix UI WorkOS asChild 既存のRadix資産がある場合

React Ariaを選ぶ理由になるのは、DatePicker・Calendar・Table・Tree・ColorPickerのように自作が重い部品を使う場合と、多言語や右から左の言語に対応する場合です。部品数は大きく違い、Headless UIは少数の基本部品に絞られています。逆に、ボタンとモーダルとメニューしか使わない小さな画面なら、React Ariaの学習コストは見合わないことがあります。

shadcn/uiは2026年7月17日にReact Ariaを正式なベースとして追加し、npx shadcn@latest init --base ariaでReact Aria版の部品を入れられるようになりました。既定はBase UIのままで、Radix UIもサポートが続いています(経緯はshadcn/uiとは?読み方・導入手順とBase UI既定化の変更点を参照)。React Aria公式もshadcnのレジストリを用意していて、npx shadcn@latest add @react-aria/cssで公式のスタイル例ごと取り込めます。既存サイトのキーボード操作や読み上げの不具合をまとめて直したい場合は、Webアクセシビリティ対応の支援も行っています。

よくある質問

React Ariaの読み方は?

「リアクト・アリア」と読みます。ariaはWAI-ARIA(Accessible Rich Internet Applications)に由来する語です。

React Ariaの公式サイトはどこですか?

2025年12月の新サイト公開以降はreact-aria.adobe.comです。旧URLのreact-spectrum.adobe.com/react-aria/は新サイトへ301で転送されます。ソースコードはGitHubのadobe/react-spectrumにあります。

React AriaとReact Spectrumの違いは?

React Spectrumは、Adobeのデザインが付いた完成品のコンポーネント群です。React Ariaはその土台になっているスタイル無しの振る舞い部分で、現行のSpectrum 2はReact Aria Componentsの上に作られています。自社デザインで作るならReact Aria Componentsを使います。

react-ariaとreact-aria-componentsはどちらを入れればいいですか?

通常はreact-aria-componentsだけで足ります。react-ariaのフックは、提供部品の構造で組めない独自要素に振る舞いを付けるときに追加します。旧来の@react-aria/buttonのような個別パッケージは新規に入れません。

React NativeでReact Ariaは使えますか?

コンポーネント版のreact-aria-componentsはreact-domに依存するため、React Nativeでは使えないと考えてください。メンテナーはフックなら動くはずと答えていますが、公式のテスト対象外です。名前の似たreact-native-ariaは別プロジェクトでリポジトリはアーカイブ済みなので、React Nativeではgluestack-uiなどReact Native向けのUIライブラリを選びます。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.11.03 テックブログ ノジマ不正アクセスで約700万件漏えい:対象確認・窓口と乗っ取り注文を止める実装
  2. 2026.10.29 テックブログ ソニー生命の情報漏洩38.5万件|ログインできない理由、再開状況と窓口の電話番号
  3. 2026.11.03 テックブログ クラブツーリズム不正アクセス:約432万件の対象確認と偽メールの見分け方・流出検知の設計
  4. 2026.11.02 テックブログ アララの不正アクセス:メール約7,700万件の持ち出しと契約企業が行うAPIキー再設定・代替送信・連名報告
  5. 2026.11.02 テックブログ サントリーの不正アクセスで約10万人分漏えい|M365のファイル大量ダウンロードを監査ログで調べる手順

RELATED POSTS 関連記事

目次