はじめに
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コンポーネントライブラリを新しく選定する機会がありましたらぜひ採用したいと思いました。皆さんも採用を検討してみてはいかがでしょうか。