Docs resource
採用ガイド
下流アプリで GunjoUI を導入するときのインストール、Next.js 設定、Tailwind 設定、テーマ適用の手順です。
GunjoUI を他の Next.js / React プロジェクトに導入する手順。5 分で Button が画面に出るところ までを目標にしています。
前提
採用先プロジェクトは以下を満たしている:
- Node.js 20 以上
- React 19 以上(peer は
^19.0.0のみ。React 18 は未サポート) - Tailwind CSS v3 または v4(peer 宣言通り)
- TypeScript(推奨。型定義
.d.tsを同梱) - Next.js 15+(推奨 16)または Vite + React
詳細は dependencies.md 参照。配布形態の方針は adoption-strategy.md 参照。
5 分インストール
1. パッケージ追加
0.0.1-alpha.0 から @gunjo/ui として npm に publish 済(現在は 0.1.0-beta.x)。beta 段階(1.0 前)のため API は変わり得るが、ドライラン採用は可:
# npm から(推奨、0.0.1-alpha.0 以降)
npm install @gunjo/ui
# 開発中(手元の clone を直接使う場合)
npm install file:../gunjo # 相対パス推奨
# あるいは絶対パス
npm install /absolute/path/to/gunjo
alpha 段階の注意:
1.0.0stable 前は API が変わる可能性あり。本格採用は0.xシリーズでのドライラン後に判断推奨。バージョン履歴は CHANGELOG.md。
2. ビルド設定(不要)
@gunjo/ui は コンパイル済みの ESM + 型定義を dist/ から配布 している(exports "." → ./dist/index.js、各コンポーネントの "use client" 境界も保持)。そのため transpilePackages は不要で、npm install してそのまま import できる(Next.js / Vite いずれも追加設定なし)。
旧 alpha(
main: "src/index.ts"で生 TS を配布していた頃)はtranspilePackages: ["@gunjo/ui"]が必須だった。dist 配布化以降は削除してよい。
⚠️ ただし RSC からのバレル import に既知の制約あり:Next.js App Router の Server Component から
import { X } from "@gunjo/ui"するとnext buildが失敗する(0.1.0-beta.2時点でも未解消・Next.js 16 / Turbopack で確認、追跡は #684)。§ Server Component からのバレル import の回避シムを参照。
3. Tailwind プリセット取り込み
採用先の Tailwind 系統で手順が分岐する。
3a. Tailwind v3 を使っている場合
tailwind.config.ts:
import type { Config } from "tailwindcss";
import gunjoPreset from "@gunjo/ui/tailwind-preset";
const config: Config = {
presets: [gunjoPreset],
content: [
"./app/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./node_modules/@gunjo/ui/dist/**/*.js", // GunjoUI のクラスもスキャン(コンパイル済み dist)
],
};
export default config;
3b. Tailwind v4 を使っている場合
v4 は tailwind.config.ts ベースではなく CSS の @theme ベース。@gunjo/ui/tailwind-preset をそのまま CSS から @config で読み込む方式が最も簡単:
/* app/globals.css */
@import "tailwindcss";
@config "../node_modules/@gunjo/ui/tailwind-preset.js";
@source "../node_modules/@gunjo/ui/dist/**/*.js";
@import "@gunjo/ui/styles"; /* 次節 4 でも触れる token 定義 */
@source で GunjoUI 内部のクラスをスキャン対象に追加する。@config を使わずに直接 @theme ブロックを書きたい場合は、@gunjo/ui/tailwind-theme-extend から token map を取り出して手で写経する形になる(メンテ負担が大きいので非推奨)。
4. グローバル CSS 取り込み
採用先の app/globals.css(Next.js App Router の場合):
@import "tailwindcss"; /* v4。v3 なら従来の @tailwind directives */
@import "@gunjo/ui/styles"; /* GunjoUI のトークン定義 */
v4 採用で前節 3b の
@configを使った場合は、@import "@gunjo/ui/styles";がその CSS 内に既にあるはずなのでここは重複させない。
create-next-app が生成する :root { --background; --foreground; } や @theme inline の既定トークンブロックが残っている場合は、GunjoUI の token と競合しないように削除するか @gunjo/ui/styles の定義へ置き換える。
⚠️ Turbopack dev の注意: Next.js 16 + Turbopack の
npm run devでは、CSS 内の bare specifier@import "@gunjo/ui/styles";が解決できず全ルートが 500 になることがある(CssSyntaxError: Can't resolve '@gunjo/ui/styles'。npm run buildは成功する dev 限定の挙動)。その場合は 下のapp/layout.tsxで JS としてimport "@gunjo/ui/styles";する形(推奨)、または CSS 側を相対パス@import "../node_modules/@gunjo/ui/dist/globals.css";にして回避する。
または app/layout.tsx:
import "@gunjo/ui/styles";
import "./globals.css";
5. 最初のコンポーネント
app/page.tsx:
import { Button, Card, CardHeader, CardContent } from "@gunjo/ui";
export default function Page() {
return (
<main className="p-8">
<Card>
<CardHeader>
<h2 className="text-xl font-semibold">GunjoUI が動いている</h2>
</CardHeader>
<CardContent>
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
</CardContent>
</Card>
</main>
);
}
npm run dev で Button が GunjoUI のスタイルで表示されれば成功。
Tailwind を使わないプロジェクト(純 CSS サブパス)
npm 不可環境向けに固定 URL で配布している Tailwind 非依存の純 CSS 資産 は、パッケージにも同梱しており subpath で import できる:
@import "@gunjo/ui/tokens.css"; /* 純 CSS トークン(:root / .dark。hsl(var(--…)) 記法) */
@import "@gunjo/ui/patterns.css"; /* gj- パターンクラス(card / badge / button / table / tabs / timeline / gantt / meter 等) */
JS からの import "@gunjo/ui/tokens.css"; でもよい(bundler が CSS import を扱える構成の場合)。
-
@gunjo/ui/stylesとの違い:styles(dist/globals.css)は Tailwind 前提のフル定義で、コンポーネント(React)利用時はこちら。tokens.css/patterns.cssは Tailwind の無いプロジェクトで GUNJO のトークンと基本パターンだけ使いたい場合に選ぶ - 中身は gunjo.jp/tokens.css / gunjo.jp/patterns.css の配信版と同一(同じソース・オブ・トゥルースから生成し drift 検証つき)。npm も使えない環境では固定 URL をコピペする(/docs/no-npm 参照)
- 公開状況:
0.1.0-beta.2から収録済み(npm 版でそのまま import できる)
Server Component からのバレル import(RSC)
現象
npm 版 @gunjo/ui@0.1.0-beta.2(それ以前の beta も同様)を Next.js 16(Turbopack)の Server Component(layout.tsx / page.tsx など)からバレル import すると、next build の Collecting page data 段階で失敗する:
TypeError: i.createContext is not a function
next dev では発生せず、transpilePackages の有無も無関係(2026-07-24 実測。詳細は #684)。
原因
Turbopack がバレル(dist/index.js)経由でモジュールを解決する際、leaf 側の "use client" 境界を正しく扱えず、createContext を含む client 専用モジュールが Server 側で評価されるため。
回避策:"use client" 再エクスポートシム
利用側プロジェクトに "use client" を付けた再エクスポートファイルを 1 枚作り、アプリからの import はすべてそこを経由させる:
// components/ui.ts
"use client";
export {
Button,
Card,
CardHeader,
CardContent,
TooltipProvider,
// 使うコンポーネントを列挙
} from "@gunjo/ui";
// app/layout.tsx(Server Component のまま)
import { TooltipProvider } from "@/components/ui";
シム自体が client 境界になるため、Server Component からでもビルドが通る。
今後の予定:コンポーネント単位の subpath exports(
@gunjo/ui/tableなど、#677)の npm 公開と推奨経路化を予定している。公開後はバレル一括解決を避けられるため、このシムは不要になる見込み。進捗は #684 を参照。
Server Components と関数prop(RSC)
一部のコンポーネントは 関数の prop(formatValue / formatTime / renderCard / renderNode など)を受け取る。これらを Server Component から直接渡すと next build が失敗する:
Error: Functions cannot be passed directly to Client Components
unless you explicitly expose it by marking it with "use server".
これは React の制約で、関数はサーバー→クライアント境界をまたげないため。tsc --noEmit も next dev も気づかず、next build(本番ビルド)だけが検出するので、最初の本番ビルドで初めて踏みがち。
対処(いずれか)
-
既定のまま使う — 関数 prop を渡さなければどのコンポーネントも RSC で安全に描画できる(既定パスはサーバー安全)。
-
シリアライズ可能な代替を使う — 数値整形の主要コンポーネントは、関数の代わりに
valueFormat("number" | "compact" | "integer"またはIntl.NumberFormatOptions)を受け取る。これは serializable なので Server Component から渡せる:// Server Component — OK(関数ではなく serializable な指定) <PieChart segments={data} valueFormat="compact" /> <GaugeChart value={72} valueFormat={{ style: "currency", currency: "JPY" }} /> -
クライアント境界で包む — 関数整形や JSX を返したい場合は、
"use client"を付けた薄いラッパーに切り出し、そこから関数 prop を渡す:"use client"; import { PieChart } from "@gunjo/ui"; export function RevenuePie({ data }: { data: { label: string; value: number }[] }) { return <PieChart segments={data} formatValue={(n) => `¥${n.toLocaleString()}`} />; }
どのコンポーネントが関数 prop を持つかは各コンポーネントの docs(Props 表)で確認できる。
valueFormat等の serializable 代替は順次追加中(#576)。
Dark Mode 有効化
GunjoUI は CSS variables ベースで、html または body に class="dark" を付けるだけで全コンポーネントが dark token に切り替わる。採用先で next-themes などのライブラリと組み合わせる場合は、採用先プロジェクトに明示的に追加する:
npm install next-themes
app/layout.tsx:
import { ThemeProvider } from "next-themes";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</body>
</html>
);
}
GunjoUI 本体には ThemeProvider / ThemeToggle も含まれているため、外部ライブラリを使わずに GunjoUI の .dark class 管理だけで始めることもできる。
L3 段階の注記:dark mode 全 70 コンポーネントの目視通しキャプチャは未取得。docs サイト(
npm run dev→:13030)でトグル切替して目視確認することを推奨。
フォント前提
GunjoUI のテキスト系コンポーネントは Inter を fontFamily に指定している。
- Next.js:
next/font/googleのInterを root layout で読み込めば OK - その他:採用先の CSS で
@import url('https://fonts.googleapis.com/css2?family=Inter...')を読む
和文(日本語)は GunjoUI 側で OS フォールバック前提。明示したい場合は採用先の CSS で font-family: Inter, "Hiragino Sans", "Yu Gothic UI", sans-serif; などを設定。
トラブルシューティング
SyntaxError: Unexpected token でビルドが落ちる
0.0.1-alpha.2 以前の生 TS 配布版を掴んでいる可能性が高い。最新版はコンパイル済み dist/ を配布しており transpilePackages 不要(§2 ビルド設定)。パッケージを更新するか、旧版なら next.config.ts に transpilePackages: ["@gunjo/ui"] を追加する。
Tailwind クラスが効かない
v3 の場合は tailwind.config.ts の content に node_modules/@gunjo/ui/dist/**/*.js を入れ忘れている可能性が高い。v4 の場合は @source ディレクティブで同等のパスを指す必要がある。Tailwind は採用先のクラス出現箇所しかスキャンしないため、library のクラスも明示する必要がある。
色が真っ黒・真っ白
@gunjo/ui/styles の import が抜けている、または順序が @import "tailwindcss" の 後 にきていない。CSS variables が定義されていないと bg-background などのクラスが空になる。
Tailwind v4 で動かない
本リポジトリの docs サイトは v4 + Next 16 で稼働確認済(dependencies.md の ✅ 行)。v4 で問題が出る場合は最初に @config のパス解決を疑う(採用先の globals.css から見た相対パスが正しいか)。それでもだめなら issue で報告。
createContext is not a function でビルドが落ちる
Server Component から @gunjo/ui をバレル import している(Next.js 16 + Turbopack、0.1.0-beta.2 時点でも未解消)。§ Server Component からのバレル import の "use client" 再エクスポートシムで回避する。
Functions cannot be passed directly to Client Components でビルドが落ちる
Server Component から関数 prop(formatValue 等)を渡している。tsc / next dev は通り next build だけが落ちる。§ Server Components と関数prop の対処(valueFormat を使う/"use client" ラッパーで包む)を参照。
次のステップ
- 既存アプリへの段階移行:migration-playbook.md
- 新規コンポーネントを足したい:component-addition.md
- バージョンアップ時の注意:versioning.md