技術系

Radix UIを使ってみた

技術系

こんにちは、なかにしです。

今回は React用のUIライブラリ、Radixを使ってみたいと思います。

ReactのUI関係は Chakra UIMUI を使うことがほとんどですが、最近はカスタマイズの為にヘッドレスUIを使うことも出てきました。

ヘッドレスUIでは Radix UI が有名らしいので、ちょっと触っておこうかなといった感じです。

ヘッドレスUIとは

「ヘッドレス○○」は最近耳にすることも多いと思います。

一番有名なのは ヘッドレスCMS ですかね。

ざっくりいうと、密結合になっているものを分離して個々で管理しようねってことです。

ヘッドレスCMSは、今までくっついていたフロントエンド(見た目)とバックエンド(機能)を分離して、バックエンドのみ提供する形にしたものです。

ヘッドレスUIも同じようなもので、見た目と機能を分離し、機能のみ提供する形にしたものです。
ヘッドレスCMSと違うのは、見た目も機能もフロントでできているという部分です。

例えば、アラートやモーダルを例に取ると、
アラートを出す「機能」やモーダルを表示・非表示にする「機能」のみ提供するのがヘッドレスUIです。

そこに、後からCSSで見た目を付けていきます。

この仕組みにより、見た目と機能が密結合だった今までと比べ、カスタムがしやすくなります。

事前準備

Viteで環境の構築をしておきます。

npm create vite

Radix UI の導入

導入は非常に簡単です。
Chakra UI とあまり変わりません。

まず、 Radix UI をインストール

npm install @radix-ui/themes

続いて、最低限のcssをインポート(main.tsxに追記)

import "@radix-ui/themes/styles.css";

ルートの場所に、Themeを配置

import { Theme } from "@radix-ui/themes";
import "@radix-ui/themes/styles.css";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./index.css";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <Theme>   // これを配置
      <App />
    </Theme>
  </StrictMode>
);

導入は完了です!

Radixコンポーネントを配置

あとは、docs にあるコンポーネントの中から使いたいものを選び、配置するだけです。

まずは、簡単な Budge を配置してみました。

import { Badge, Flex } from "@radix-ui/themes";
import "./App.css";

function App() {
  return (
    <Flex gap="2">
      <Badge>In progress</Badge>
      <Badge>In review</Badge>
      <Badge>Complete</Badge>
    </Flex>
  );
}

export default App;

▼ バッヂができました。かわいいですね。

ここに、Radix UI側が用意してくれている引数colorを設定し、色を付けます。

import { Badge, Flex } from "@radix-ui/themes";
import "./App.css";

function App() {
  return (
    <Flex gap="2">
      <Badge color="orange">In progress</Badge> // 色を付ける
      <Badge color="blue">In review</Badge> // 色を付ける
      <Badge color="green">Complete</Badge> // 色を付ける
    </Flex>
  );
}

export default App;

▼ 色が付きました。かわいいですね。

style引数に独自スタイルを設定することができます。
orange の Budgeにスタイルを付けました。

import { Badge, Flex } from "@radix-ui/themes";
import "./App.css";

function App() {
  return (
    <Flex gap="2">
      <Badge style={{ width: "400px", height: "300px" }} color="orange">
        In progress
      </Badge>
      <Badge color="blue">In review</Badge>
      <Badge color="green">Complete</Badge>
    </Flex>
  );
}

export default App;

▼ でかバッヂです。かわいいですね。

特徴的なのは、Context Menu や Dialog などの「機能」を持ったコンポーネントですね。

Dialog を見てみます。

<Dialog.Root>
	<Dialog.Trigger>
		<Button>Edit profile</Button>
	</Dialog.Trigger>

	<Dialog.Content maxWidth="450px">
		<Dialog.Title>Edit profile</Dialog.Title>
		<Dialog.Description size="2" mb="4">
			Make changes to your profile.
		</Dialog.Description>

		<Flex direction="column" gap="3">
			<label>
				<Text as="div" size="2" mb="1" weight="bold">
					Name
				</Text>
				<TextField.Root
					defaultValue="Freja Johnsen"
					placeholder="Enter your full name"
				/>
			</label>
			<label>
				<Text as="div" size="2" mb="1" weight="bold">
					Email
				</Text>
				<TextField.Root
					defaultValue="freja@example.com"
					placeholder="Enter your email"
				/>
			</label>
		</Flex>

		<Flex gap="3" mt="4" justify="end">
			<Dialog.Close>
				<Button variant="soft" color="gray">
					Cancel
				</Button>
			</Dialog.Close>
			<Dialog.Close>
				<Button>Save</Button>
			</Dialog.Close>
		</Flex>
	</Dialog.Content>
</Dialog.Root>

機能がついているコンポーネントは、
「Root」で囲み、その中に動きが出る部品を入れていくような形を取ります。

この辺りは、公式ドキュメントを参考にしながら設定していきます。

ここが最大の特徴であり、難しい部分です。

今までは <Dialog /> のように一つ、もしくは2,3個程度のコンポーネントで構成されているものが多かったのですが、ヘッドレスUIはこの部分を分解することで、カスタマイズ性を高めています。

さいごに

今回は、ヘッドレスUIの Radix UI を触ってみました。

触ってみた感想としては、決定的な違いがあるという実感は正直なところ持てませんでした。

個人的には、設計思想の違いかな?と思います。

ヘッドレスではないUIライブラリは
「スタイルはこっちで用意する。気に入らないなら変えて」

ヘッドレスUIは
「最低限のスタイルはこっちで用意するから、変える前提でお願い」

のようなスタンスなのかなと。

思い返すと、Muiはスタイルを設定してもデフォルトのスタイルに負けて反映されなかったこともあるので、CSSカスタマイズを基本的に行うか否かで使い分けるべきかなと思いました。

今回はここまで!
Enjoy Hacking!!