2024年02月21日
Park UI + Panda CSSでReact Server Components(RSC)に対応
ヘッドレスコンポーネントライブラリArk UIのコンポーネントをゼロランタイムCSS in JSでスタイリングしたUIコンポーネントライブラリPark UIを使ってNext.jsのApp Routerに対応する記事です。
動機
Next.js v13で導入された App Router では React Server Components(RSC) の理解が必須となります。しかしながら Material-UI や Chakra UI など従来のReactコンポーネントライブラリのスタイルシステムは Emotion ベースであることが多く、2024年2月現在でRSCへの対応が不十分であり、新たにApp Routerを学びたい場合にUIデザインは障壁となります。
Park UIとは
Ark UIのコンポーネントをゼロランタイムCSS in JSでスタイリングしたUIコンポーネントライブラリです。通常UIコンポーネントライブラリはReactやVueなど特定のフレームワークにのみ対応していますが、Park UIはReact, Vue, Solidで使うことができます。というのも、Park UIはドキュメントからコンポーネントのコードをコピー&ペーストして使用するからです。
Park UIの特徴としてスタイルシステムは Tailwind CSS と Panda CSS のどちらか好きな方を選択することができます。
Ark UIとは
Ark UI は Chakra UI の開発チームによるヘッドレスコンポーネントライブラリです。ヘッドレスコンポーネントライブラリとはスタイルを持たないコンポーネントライブラリのことで、コンポーネントからスタイルを排除しアクセサビリティの実装やインタラクティブな機能面を抜き出すことで、ユーザーが柔軟にカスタマイズすることができます。
Panda CSSとは
Chakra UIの開発チームによるゼロランタイムCSS in JSライブラリです。Tailwind CSSに大きな影響を受けていますが、Tailwind CSSと決定的に異なる点は、独自のクラス名を覚える必要はなく、従来のCSS in JSのようにオブジェクトとして堅安全性を保ちながらスタイルを記述できる点です。
各ライブラリの関係性
- Chakra UI : Reactコンポーネントライブラリ
- Zag : Chakra UIが開発するロジック・ステート制御のライブラリ
- Ark UI : Chakra UIが開発するZagをベースとしたヘッドレスコンポーネントライブラリ
- Panda CSS : Chakra UIが開発するゼロランタイムCSS in JSライブラリ
- Park UI : Ark UIをPanda CSSまたはTailwind CSSでスタイリングしたコンポーネントライブラリ(Chakra UI開発チーム所属の個人によるサードパーティ)
将来的にはChakra UI v3がZag, Ark UI, Panda CSSで構成される予定です。Park UIは現時点でPanda CSSを使ってRSCに対応する有効な手段であると同時に、Chakra UI v3の導入の準備にもなります。
将来的にChakra UIはZag, Ark UI, Panda CSSで構成される予定です。ただし開発中のChakra UI v3は引き続きEmotionをベースとすることが明言されています。
2024/03/29追記 やはりChakra UI v3はZag, Ark UI, Panda CSSで構成されるようです。
どのような場合に向いているか
- Next.jsのApp Router、React Server Components(RSC)に対応したい
- ゼロランタイムCSS in JSを使いたい
- でも基礎的なコンポーネントを一から設計するのは面倒
- Tailwind CSSの記法が苦手 (Panda CSSを使いたい)
自分はTailwind CSSの記法が苦手なのでPanda CSSが使えるライブラリを探した結果Park UIに行き着きましたが、Tailwindに馴染みがある方であればPark UIに影響を与えたライブラリに shadcn/ui があり、こちらの方が日本語の情報も多いと思われます。
環境
ここではNext.js(App Router) + Panda CSSの環境を前提としています。
- @ark-ui/react: ^2.0.1
- @pandacss/dev: ^0.31.0
- @park-ui/panda-preset: ^0.33.0
- next: 14.1.0
- react: ^18
- react-dom: ^18
準備
- Next.js(App Router)とPanda CSSの導入
- インストール
- Panda ConfigファイルにPark UIプリセットを設定
- コンテキストファイルを配置
- TSConfigのパスと
park-ui.json
を設定(任意)
0. Next.js(App Router)とPanda CSSの導入
1. インストール
ここからはPark UI公式ドキュメントのGetting Startedに沿って説明します。
# Ark UIをインストール
npm install @ark-ui/react
# Park UIのPanda Presetを作成
npm install --save-dev @park-ui/panda-preset
2. Panda ConfigファイルにPark UIプリセットを設定
ここではPanda CSSを使っているので、panda.config.ts
にPark UIプリセットを追加します。
// panda.config.ts
import { defineConfig } from "@pandacss/dev";
import { createPreset } from "@park-ui/panda-preset";
export default defineConfig({
preflight: true,
presets: [
"@pandacss/preset-base",
createPreset({
accentColor: "blue",
grayColor: "sand",
borderRadius: "xl",
}),
// or "@park-ui/panda-preset"
],
include: ["./src/**/*.{js,jsx,ts,tsx}"],
exclude: [],
jsxFramework: "react",
outdir: "styled-system",
});
この例ではcreatePreset
関数を使ってアクセントカラーにblue
、グレーカラーにsand
、borderRadiusにxl
を設定していますが、Park UIデフォルトのプリセットを使う場合は"@park-ui/panda-preset"
という文字列を配列に記述すればOKです。
Park UIのプリセットによってPanda CSSのrecipes
やpatterns
を生成し、それをコンポーネントで利用するという仕組みです。
3. コンテキストファイルを配置
まずプロジェクト内のPark UIのコンポーネントを置くディレクトリと、Park UIコンテキストを置くディレクトリを決定します。この例では以下のように設定します。
- Park UIコンポーネント:
src/components/ui
- Park UIコンテキスト:
src/lib
Park UIコンテキストのディレクトリ(src/lib
)にcreate-style-context.tsx
を作成し、Park UIドキュメントからコピー&ペーストします。React Server Components(RSC)を使う場合は冒頭に"use client"
ディレクティブを記載します。
4. TSConfigのパスとpark-ui.json
を設定 (任意)
この設定はPark UI CLIを使う場合必要になります。
TSConfig
{
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@styled-system/*": ["./styled-system/*"]
}
}
park-ui.json
park-ui.json
は後述するPark UI CLIを使用する場面で必要になります。Park UI CLIによる自動コピー機能を使わない場合は必要ありません。importAliases
には3.で決定したPark UIコンポーネントディレクトリと、Park UIコンテキストのディレクトリを設定します。
{
"cssFramework": "panda",
"jsFramework": "react",
"importAliases": {
"components": "@/components/ui",
"utils": "@/lib"
},
"useReactServerComponents": true
}
コンポーネントの使い方
Park UIのコンポーネントは通常のUIライブラリとは異なり、コンポーネントのコードをディレクトリにコピー&ペーストして使用します。例えばPark UIの<Button>
コンポーネントを使う場合、Park UIのウェブサイトに記載されているコードをコピーし、button.tsx
としてディレクトリの任意の場所に置く必要があります。
この例ではsrc/components/ui
をPark UIコンポーネントのディレクトリとしているので、src/components/ui/button.tsx
というファイルを作成して、下記リンクの「Installation」>「1. Add Component」のコードをコピー&ペーストします。
具体的な使い方は各コンポーネントのUsageのコードを参考にするといいでしょう。
コンポーネントのProps
各コンポーネントのPropsの内容はArk UIのAPI Referenceを参照することになります。Park UIドキュメントの各コンポーネントのヘッダ画面にリンクが配置されています。
Park UI CLIによる自動コピー
Park UI CLIでは前述の通りコマンドラインによってコンポーネントの自動コピーが可能です。Park UI CLIを使うにはpark-ui.json
が必要です。
# park-ui.jsonを生成
npx @park-ui/cli init
# buttonコンポーネントをコピー
npx @park-ui/cli add button
# 全てのPark UIコンポーネントをコピー
npx @park-ui/cli add --all
Park UI 使用における留意点
React Server Components (RSC)を使う場合
Park UIコンテキストに依存するコンポーネントには先頭に"use client"
ディレクティブを記載する必要があります。Park UI CLIを使用する場合は、park-ui.json
のuseReactServerComponents
をtrue
にしておくと自動コピーの際に必要なコンポーネントに対して"use client"
ディレクティブを自動で付けてくれます。
独自のSemantic Tokens
Park UIはPanda CSSやTailwindのTokensの値を使って独自のSemantic Tokensを生成しています。ただしPanda CSSやTailwindのTokensを改変する形であるため、これらのツールを既に使ったことがある人にとっては少し引っかかるポイントになります。
- パレットを12段階に新たに正規化している (例:
red.50
がred.1
になる) - パレットの
shades
がダークモードで明暗が逆転する (例: ライトモードのred.12
は暗色だがダークモードのred.12
は明色)
この仕様は Radixのカラーシステム に則っているようです。
カスタマイズの方法
panda.config.ts
で既存のテーマを拡張(extend
)することでPark UIのプリセットをカスタマイズすることができます。
まとめ
Chakra UIは 2023年中にゼロランタイムCSS in JSの導入とRSCに対応するv3をリリースする予定でした が、2024年2月現在v3はリリースされていません。
Chakra UIは将来的に自前のゼロランタイムCSS in JSであるPanda CSSを導入する予定です。
Excited to bring together all the projects we've been working on into @chakra_ui v3
— Sage ⚡️ (@thesegunadebayo) March 28, 2024
🟡 Styling API from Panda
🟠 Headless primitives from Ark
⚫️ Component recipes from Park UI
Coming together nicely 🤩. We're pretty close! pic.twitter.com/1mgdyL8vSK
また Material-UIも2024年6月までにv6をリリースし、ゼロランタイムCSS in JSの導入とRSCに対応する予定 です。
今後主流になっていくと思われるゼロランタイムCSS in JSやRSCの準備運動としてPark UIを使ってみてはいかがでしょうか。
リンク
It Ain’t Over ‘til It’s Over / Lenny Kravitz (1991)
Panda CSS
Panda CSSは型安全を保ちながらスタイルを記述することができるCSS-in-JSのパッケージです。
https://panda-css.com/