はじめに
Radix UIのPrimitivesを使ったことはありますか?
ヘッドレスなUIコンポーネントを提供してくれるライブラリとして有名で単にRadix UIとも呼ばれます(似たようなライブラリとしては最近でたArk UIなどがあります)。
このようなライブラリはUIを見た目と振る舞いに分けたうちの振る舞いだけを実装したコンポーネントを提供しています。そのため、Material UIやChakra UIのようなスタイリングも含むUIコンポーネントライブラリでは強制されていたスタイリング方法から抜け出して自由度を持ったスタイリングができるとして人気です。
そんなライブラリを開発していたRadix UIですが、新たにThemesと呼ばれるコンポーネントライブラリの提供を2023年の8月8日から開始しました。
この記事ではThemesの使い方と特徴を簡単に紹介します。
Themes
Themesの説明が遅れてしまいました。ThemesはUIコンポーネントライブラリです。
Primitiveとは異なりスタイリングも振る舞いも兼ねたMaterial UIやChakra UIに近いライブラリです。
コンポーネントの設計指針は以下のように掲げられております。
An open-source component library optimized for fast development, easy maintenance, and accessibility.
迅速な開発、容易なメンテナンス、アクセシビリティのために最適化されたオープンソースのコンポーネントライブラリです。
スタイリングは純粋なCSSを用いて行われており、他のUIコンポーネントライブラリでよく使われているemotionなどに依存していないところも特徴です。
さらにRSCにも対応しています。対応していると言っても全てのコンポーネントにuse clientディレクティブを用いた暫定的な対応ではなく、クライアント側のコンポーネントとサーバー側のコンポーネントをちゃんと使い分けた実装がなされています。
Themesには便利なページがあります。
全体でカスタマイズ可能な項目を選択しながらコンポーネントの一覧を見ることができるplaygroundです。一覧性が高く、標準からカスタマイズした姿が見られるのでとても感動しました。開発する前に全貌を把握できるのでとても便利です。
導入する
Nextjsのプロジェクトを用いて導入を進めてみます。他のプロジェクトでも同様に導入可能です。
アプリの下準備としてNextjsのプロジェクトを作ります。
pnpm create next-app
いくつか質問されますがほとんどはデフォルトで回答します。tailwindcssは利用しないのでnoを選択します。
noを選択してもCSS Modulesを用いたプロジェクトが建つのでglobals.cssやpage.modules.cssを削除します。さらにlayout.tsxからファイルの参照を消して、page.tsxからファイルの参照とJSXを書き換えるために空にしておきます。
export default function Home() {
return <></>
}
これでNextjsアプリの作成とスタイリングの排除が完了しました。
次にThemesを導入していきます。
まずはパッケージのインストールです。
pnpm install @radix-ui/themes
続いて、layout.tsxにアプリ全体で設定したいThemesが提供するCSSを配置します。
import '@radix-ui/themes/styles.css';
他のフレームワークの場合はどこにアクセスした時も呼び出すところに配置してください(remixだとroot.tsxとか)。
そして、Themes全体のカスタマイズのためにThemeコンポーネントをlayout.tsxに定義します。
import { Theme } from '@radix-ui/themes';
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import '@radix-ui/themes/styles.css';
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
<Theme>
{children}
</Theme>
</body>
</html>
)
}
これで準備は完了です。好きなコンポーネントを@radix-ui/themesから呼び出して利用していきましょう!
import { Flex, Text, Button } from '@radix-ui/themes';
export default function MyApp() {
return (
<Flex direction="column" gap="2">
<Text>Hello from Radix Themes :)</Text>
<Button>Let's go</Button>
</Flex>
);
}
Themeによるカスタマイズ
Themeコンポーネントではアプリ全体の基本となる色、カラーモード、ビジュアルスタイルを設定します。
Themeコンポーネントの設定をするときはThemePanelコンポーネントを用いることをお勧めします。
ThemePanelコンポーネントはThemeコンポーネントでカスタマイズ可能な項目を変更するパネルを画面に表示させられます。

開発初期の段階ではかなり助かる機能だと考えています。
色
アプリケーションの中心となる色としてアクセントカラーを、グレースケールの中心カラーとしてグレーカラーを選択します。
<Theme accentColor="lime" grayColor="olive">
アクセントカラーは全23種類あります。選択した色に対応して文字の色も決まります。
グレーカラーは全6種類あります。
アクセントカラーとグレーカラーの組み合わせに悩んだ場合はおすすめの組み合わせが提供されているので参考にしてください。
カラーモード
デフォルトではライトモードに設定されています。Themeのappearanceをdarkに設定することでダークモードに変更できます。
<Theme accentColor="lime" grayColor="olive" appearance="dark">
カラーモードの設定はクライアント側で要素に対するクラスの追加によって行われるのでエラーが発生します。
以下のようにhtmlにsuppressHydrationWarningを追加して抑制させてください。
<html lang="en" suppressHydrationWarning>
カードなどの背景
Themesではデフォルトの状態ではカードやテーブルの背景は半透過しています。

透過させたくない場合はpanelBackgroundでsolidにすることで等価を失わせられます。
<Theme panelBackground="solid">
角丸
コンポーネントの境界の外側の角に対する丸みを決めます。
<Theme radius="medium">
コンポーネント
コンポーネントは大きくレイアウトとタイポグラフィ、コンポーネントの3つに分けられます。
レイアウトはBoxやFlexのようなコンポーネントを組み合わせるときや整理する時に利用するコンポーネントです。
タイポグラフィはTextやHeadingのようなテキストを表すためのコンポーネントです。
コンポーネントはAccordionやCheckBoxのような機能を持ったコンポーネントです。
レイアウトにSectionがあったり、タイポグラフィにEmがあったりhtmlの要素のセマンティクスに配慮しやすいコンポーネントが多くアクセシビリティへの配慮を感じました。
スタイリング
コンポーネントへのスタイリングは引数を用いて行います。量が多いので頭出しだけですが、Boxに対して4pxのpaddingを設けたい場合は以下のように設定します。
<Box p="1" />
pに1を指定して4pxのpaddingを実現しました。この値はThemesで指定されたCSS変数によって定まりました。
このケースではデフォルトのファイルにある--space-1を元に4pxとなりました。
.radix-themes {
--space-1: calc(4px * var(--scaling));
--space-2: calc(8px * var(--scaling));
--space-3: calc(12px * var(--scaling));
--space-4: calc(16px * var(--scaling));
--space-5: calc(24px * var(--scaling));
--space-6: calc(32px * var(--scaling));
--space-7: calc(40px * var(--scaling));
--space-8: calc(48px * var(--scaling));
--space-9: calc(64px * var(--scaling));
}
このようにコンポーネントで指定する値の多くはThemesが定義したCSS変数によって決まります。それをtheme-config.cssファイルに上書きして定義してカスタマイズできます。theme-config.cssはlayout.tsxのようなルートファイルで@radix-ui/themes/styles.cssと合わせて呼び出す必要があります。
.radix-themes {
--space-1: 4px;
}
CSS変数がまとまったデフォルトの設定はこちらに書かれています。
おわりに
新たなUIコンポーネントライブラリThemesを紹介しました。playgroundやThemePanelなどスタイリングに関するDXがとても良いところが印象的でした。
後発のライブラリですので、これまでのUIコンポーネントライブラリやPrimitivesを開発して来たプラクティスが生かされていますし、RSC対応もちゃんとされています。
さらに、既存のUIコンポーネントライブラリの多くが採用しているemotionを利用していないのでサーバー側でのレンダリングにおけるパフォーマンス上の問題も生じません。
このようなところから、これからのUIコンポーネントライブラリとして台頭してくると考えています。
UIコンポーネントライブラリを新しく選定する機会がありましたらぜひ採用したいと思いました。皆さんも採用を検討してみてはいかがでしょうか。

