はじめに
「アクセシブルなUIコンポーネントを一から自作するのは大変そうだけど、かといって既存のUIライブラリはデザインの自由度が低くて自社ブランドに馴染まない」——そんなジレンマを感じたことはないでしょうか。特にtoB向けの管理画面やダッシュボードでは、見た目の作り込みよりも「正しく動くこと」「誰でも使えること」が優先されがちですが、その品質を担保するためのコストは決して小さくありません。
React Spectrumは、このジレンマに対して「Adobeが実運用で磨き上げたデザインシステムを、そのままコンポーネントとして使う」という解決策を提示してくれるライブラリです。ゼロからスタイルを組み上げる必要がなく、アクセシビリティ対応済みの完成度の高いUIをすぐに導入できます。
とはいえ、読むより触った方が早いと思います。Providerによるテーマ切り替えとTextFieldのリアルタイムバリデーションが動くサンプルを用意したので、先に挙動を見たい方はこちらからどうぞ。
React Spectrumとは
React Spectrumは、Adobeが開発・公開しているReact向けUIコンポーネントライブラリです。Adobeの公式デザインシステムである「Spectrum」をReactで実装したもので、Photoshop on the webやAdobe Expressなど、Adobe自身の製品群でも実際に使われています。
内部的にはアクセシビリティロジックを担うReact Aria、状態管理を担うReact Statelyという2つのライブラリの上に構築されており、これらにあらかじめSpectrumデザインのスタイルが適用された状態で提供されるのがReact Spectrumだとイメージすると分かりやすいです。
主な特徴
- アクセシビリティ標準装備 - WAI-ARIA Authoring Practicesに準拠した実装で、スクリーンリーダーやキーボード操作への対応を意識せずとも自然に満たせます
- すぐ使えるデザイン品質 - Adobe製品で実証済みのSpectrumデザインシステムをそのまま利用でき、配色やスペーシングを1から検討する手間が省けます
- マウス・タッチ・キーボードへの適応 - 入力デバイスを問わず一貫した操作感を提供し、レスポンシブなレイアウトにも対応します
- 国際化対応済み - 30以上の言語、右から左に書く言語(RTL)、各種の日付・数値フォーマットを標準でサポートします
- ダークモード対応 - テーマ機能を通じて、ライト/ダークの切り替えを簡単に組み込めます
インストール
すべてのコンポーネントがまとまった@adobe/react-spectrumパッケージをインストールします。
# npm
npm install @adobe/react-spectrum
# yarn
yarn add @adobe/react-spectrum
# pnpm
pnpm add @adobe/react-spectrum
React Spectrumのサンプルを動かす
まずは実際に手を動かして、React Spectrumの感触を掴んでみましょう。以下のサンプルでは、ProviderのcolorSchemeを切り替えてダークモードに反転させたり、TextFieldのvalidationStateを使ったリアルタイムバリデーションを試したりできます。お名前欄を空にするとvalidationStateがinvalidに変わり、エラーメッセージが表示されると同時にButtonがisDisabledで押せなくなる様子を確認してみてください。
React Spectrumのコンポーネントを使う際の骨格は、次のようにProviderでラップし、colorSchemeやTextFieldのvalidationStateを状態と連動させる形になります。
import { Provider, defaultTheme, Switch, TextField } from "@adobe/react-spectrum";
function ThemeableForm({ isDark, name, onNameChange }) {
return (
<Provider theme={defaultTheme} colorScheme={isDark ? "dark" : "light"}>
<Switch isSelected={isDark}>ダークモード</Switch>
<TextField
label="お名前"
value={name}
onChange={onNameChange}
isRequired
validationState={name.trim() === "" ? "invalid" : "valid"}
errorMessage="お名前を入力してください"
/>
</Provider>
);
}
実際に動かせるものが下です。スイッチを操作するとcolorSchemeがlightとdarkの間で切り替わり、配色がコンポーネント全体に伝播します。お名前欄の文字を消してから戻すと、validationStateとエラーメッセージ、Buttonの活性状態が連動して変化するのが分かります。
ここで押さえておきたいのは、ProviderのcolorSchemeを変えるだけで配下のすべてのコンポーネントの配色が一括で反転する点と、onClickではなくonPressでボタン操作を扱っている点です。validationStateを自前で計算して渡しているだけで、エラー表示やアクセシビリティ属性(aria-invalidなど)はReact Spectrum側が自動的に付与してくれます。
基本的な使い方
React Spectrumのコンポーネントは、必ずProviderでラップして使用します。Providerはテーマ(配色モード)や国際化のロケール情報をアプリ全体に伝える役割を持ちます。
import { Provider, defaultTheme, Button, Flex } from "@adobe/react-spectrum";
function App() {
return (
<Provider theme={defaultTheme} colorScheme="light">
<Flex direction="column" gap="size-200" width="size-3000">
<Button variant="accent" onPress={() => alert("送信しました")}>
送信する
</Button>
</Flex>
</Provider>
);
}
export default App;
onClickではなくonPressを使う点に注目してください。これはReact Ariaの仕組みにより、マウスクリック・タッチ・キーボード(Enter/Space)のすべてを1つのイベントとして扱えるようにするためです。
フォーム入力もアクセシビリティ属性が自動で付与されます。
import { TextField, Form, Button } from "@adobe/react-spectrum";
import { useState } from "react";
function ProfileForm() {
const [name, setName] = useState("");
return (
<Form maxWidth="size-3600">
<TextField
label="お名前"
value={name}
onChange={setName}
description="表示名として使用されます"
isRequired
/>
<Button type="submit" variant="cta">
保存する
</Button>
</Form>
);
}
labelやdescriptionをpropsとして渡すだけで、対応する<label>要素の関連付けやスクリーンリーダー向けの説明文が自動的に組み込まれます。
実践的なユースケース
React Spectrumの使い方には、大きく分けて「コレクション表示」「フォーム部品」「レイアウト」の3つのパターンがあります。それぞれ実際に動かせるサンプル付きで見ていきましょう。
コレクション系:TableViewで選択可能な一覧を作る
管理画面などでよく使う「データ一覧のテーブル表示」も、React SpectrumのTableViewなら少ないコードで実装できます。
import {
TableView,
TableHeader,
TableBody,
Column,
Row,
Cell,
} from "@adobe/react-spectrum";
function UserTable() {
const columns = [
{ name: "名前", key: "name" },
{ name: "メール", key: "email" },
{ name: "権限", key: "role" },
];
const rows = [
{ id: 1, name: "田中太郎", email: "tanaka@example.com", role: "管理者" },
{ id: 2, name: "佐藤花子", email: "sato@example.com", role: "編集者" },
];
return (
<TableView aria-label="ユーザー一覧" selectionMode="multiple" height="size-3000">
<TableHeader columns={columns}>
{(column) => <Column key={column.key}>{column.name}</Column>}
</TableHeader>
<TableBody items={rows}>
{(item) => (
<Row key={item.id}>
{(key) => <Cell>{item[key]}</Cell>}
</Row>
)}
</TableBody>
</TableView>
);
}
このコードだけで、キーボードによる行選択・複数選択・矢印キーでのセル移動といった操作が自動的に有効になります。同様の機能をゼロから自作しようとすると、フォーカス管理やARIA属性の設計だけでかなりの工数がかかるため、その差は歴然です。
実際に行を選択できる状態で動かせるのが下のサンプルです。selectionMode="multiple"とselectedKeys・onSelectionChangeを組み合わせることで、チェックボックスやShift+クリックによる複数選択の状態をSetとして受け取れます。
selectionModeを"single"に変えると1行しか選択できなくなり、selectedKeysの管理もそれに応じて単純化できます。逆に選択機能自体が不要ならselectionModeごと省略すれば、通常の一覧表示だけのTableViewになります。
フォーム部品を組み合わせて入力フォームを作る
招待フォームや設定画面のように、複数のフォーム部品を組み合わせる場面もよくあります。React SpectrumではPicker(ドロップダウン選択)、NumberField(数値入力)、Checkboxをそのまま組み合わせるだけで、アクセシブルな入力フォームが作れます。
import { Picker, Item } from "@adobe/react-spectrum";
function RolePicker({ role, onChange }) {
return (
<Picker label="権限" selectedKey={role} onSelectionChange={onChange}>
<Item key="admin">管理者</Item>
<Item key="editor">編集者</Item>
<Item key="viewer">閲覧者</Item>
</Picker>
);
}
下のサンプルでは、Pickerで選んだ権限・NumberFieldで入力した招待人数・Checkboxの同意状態が、そのままリアルタイムに下部のメッセージへ反映されます。
Checkboxのチェックを外すとメッセージが「できません(要同意)」に切り替わります。フォームの送信可否をこの状態と連動させたい場合は、ButtonのisDisabledに!agreeを渡すだけで済みます。Pickerの選択肢を増やしたいときはItemを追加し、keyをそのまま状態の値として使えます。
レイアウトコンポーネントで画面を組み立てる
React Spectrumは個々のコンポーネントだけでなく、GridやViewといったレイアウト用のコンポーネントも提供しています。CSS Gridのgrid-template-areasに相当する構成を、Spectrumのデザイントークン(size-*やgray-*などのスケール)付きで宣言的に書けるのが特徴です。
import { Grid, View } from "@adobe/react-spectrum";
function DashboardLayout() {
return (
<Grid
areas={["header header", "sidebar content"]}
columns={["1fr", "3fr"]}
rows={["size-800", "auto"]}
gap="size-100"
>
<View gridArea="header" backgroundColor="blue-400" />
<View gridArea="sidebar" backgroundColor="purple-400" />
<View gridArea="content" backgroundColor="green-400" />
</Grid>
);
}
areasに渡した文字列配列がそのままCSS Gridの領域名になり、各ViewはgridAreaでどの領域に配置するかを指定します。下のサンプルではスイッチを操作して、2カラムのダッシュボードレイアウトと縦積みレイアウトを切り替えられます。
stackedがtrueのとき、areasの配列はheader・sidebar・contentが縦に1つずつ並ぶ構成に変わり、columnsも1カラムになります。レスポンシブ対応の管理画面レイアウトを組むときは、このareasとcolumnsの組み合わせを画面幅に応じて切り替える形がそのまま使えます。
ほかにも、日付選択が必要な予約フォームではDatePickerやRangeCalendar、通知表示にはToastQueueなど、業務アプリケーションで頻出するUIパターンが一通り揃っています。デザインを都度検討する必要がないため、プロトタイプから本番運用まで一貫したスピード感で開発を進められます。
まとめ
React Spectrumは、Adobeが自社製品で培ったデザインシステムとアクセシビリティ実装をそのまま享受できる、完成度の高いReact UIライブラリです。Providerでラップするだけで国際化やテーマ管理が始まり、TextFieldやTableViewのようなコンポーネントを組み合わせるだけでアクセシブルなUIが自然と出来上がります。
「デザインの自由度は多少犠牲にしてでも、正しく動くUIを素早く用意したい」という場面、特に社内ツールや管理画面の開発では非常に強力な選択肢になるはずです。もしスタイルを完全に自前で作り込みたい場合は、同じ基盤を持つReact Ariaとの使い分けも検討してみてください。