React components based on Digital Agency Design System with Tailwind CSS.
gftdデザインシステムのReact / Tailwind CSSコンポーネントライブラリです。
ベース情報: このライブラリはデジタル庁デザインシステムをベースに、gftd独自の要件に合わせてカスタマイズしたものです。
npm install @gftdcojp/ui
このライブラリを使用するには、以下の依存関係をプロジェクトに追加する必要があります:
npm install @digital-go-jp/tailwind-theme-plugin tailwindcss react react-dom
@digital-go-jp/tailwind-theme-plugin
は必須の依存関係です。このプラグインなしでは、コンポーネントのスタイルが正常に表示されません。
将来的に、gftdcojp独自のテーマプラグイン @gftdcojp/tailwind-theme-plugin
に移行予定です。現在は、オリジナルのデジタル庁プラグインを使用しています。
このコンポーネントライブラリは、標準のTailwind CSSにはない、デジタル庁デザインシステム由来の専用クラスを多数使用しています:
-
カラー:
border-solid-gray-600
,bg-blue-900
,text-solid-gray-800
など -
タイポグラフィ:
text-std-28B-150
,text-dns-16N-120
,text-oln-16N-100
など -
その他:
rounded-8
(カスタムボーダー半径) など
これらのクラスは @digital-go-jp/tailwind-theme-plugin
で定義されており、プラグインなしでは全てのコンポーネントが正常にスタイルされません。
tailwind.config.js
にプラグインを追加:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx,mdx}',
'./node_modules/@gftdcojp/ui/dist/**/*.{js,ts,jsx,tsx}'
],
theme: {
extend: {},
},
plugins: [
require('@digital-go-jp/tailwind-theme-plugin')
],
}
src/styles/globals.css
または同等のファイルに:
@tailwind base;
@tailwind components;
@tailwind utilities;
import { Button, Input, Label } from '@gftdcojp/ui';
function MyComponent() {
return (
<div>
<Label htmlFor="input">ラベル</Label>
<Input id="input" placeholder="プレースホルダー" />
<Button>送信</Button>
</div>
);
}
import {
Button,
Input,
Label,
Select,
Checkbox,
ErrorText,
SupportText
} from '@gftdcojp/ui';
function ContactForm() {
return (
<form>
<div>
<Label htmlFor="name">お名前</Label>
<Input id="name" placeholder="山田太郎" />
<SupportText>本名を入力してください</SupportText>
</div>
<div>
<Label htmlFor="email">メールアドレス</Label>
<Input id="email" type="email" placeholder="example@example.com" />
<ErrorText>有効なメールアドレスを入力してください</ErrorText>
</div>
<div>
<Label htmlFor="category">お問い合わせ種別</Label>
<Select id="category">
<option value="">選択してください</option>
<option value="general">一般的なお問い合わせ</option>
<option value="support">サポート</option>
<option value="bug">バグ報告</option>
</Select>
</div>
<div>
<Checkbox id="agree">
<Label htmlFor="agree">利用規約に同意します</Label>
</Checkbox>
</div>
<Button type="submit">送信</Button>
</form>
);
}
- フォーム: Button, Input, Label, Select, Checkbox, Radio, Textarea
- 表示: Link, UtilityLink, Divider, ErrorText, SupportText
- レイアウト: Accordion, Breadcrumbs, Disclosure, Drawer
- 通知: EmergencyBanner, NotificationBanner
- ナビゲーション: HamburgerMenuButton, LanguageSelector
- その他: RequirementBadge, Legend, Ol, Ul
このライブラリはデジタル庁デザインシステムをベースに、gftd独自の拡張を加えたものです。
git clone https://github.com/gftdcojp/design-system-example-components.git
cd design-system-example-components
npm install
npm run storybook
MIT License
monorepo 環境でワークスペースパッケージのインポートに失敗する場合の解決策を提供します。
{
"name": "@gftdcojp/ui",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.cjs.js",
"import": "./dist/index.es.js"
},
"./styles": {
"default": "./dist/styles.css"
},
"./dist/styles.css": "./dist/styles.css"
}
}
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig({
resolve: {
alias: {
'@gftdcojp/ui': resolve(__dirname, '../dist/index.es.js'),
'@gftdcojp/ui/styles': resolve(__dirname, '../dist/styles.css'),
},
conditions: ['import', 'module', 'browser', 'default'],
},
server: {
fs: {
allow: ['..'], // workspace全体へのアクセス許可
},
},
optimizeDeps: {
include: ['@gftdcojp/ui'],
},
});
packages:
- "packages/*"
- "examples"
{
"dependencies": {
"@gftdcojp/ui": "workspace:*"
}
}
// スタイルのインポート
import '@gftdcojp/ui/styles';
// コンポーネントのインポート
import { Button, Input, NotificationBanner } from '@gftdcojp/ui';
function App() {
return (
<div>
<Button variant="primary">Hello World</Button>
<Input placeholder="Enter text" />
</div>
);
}
エラー | 解決策 |
---|---|
Failed to resolve import |
Vite/Next.js alias設定を確認 |
Module not found |
workspace: 依存関係を確認 |
CSS not loaded |
styles exports設定を確認 |
Type errors |
TypeScript paths設定を確認 |
エラー | 原因 | 解決策 |
---|---|---|
Module parse failed |
transpilePackages設定不足 |
next.config.js にtranspilePackages: ['@gftdcojp/ui'] 追加 |
CSS not loading in production |
CSS抽出設定 | PostCSS設定とTailwind content設定を確認 |
'use client' directive missing |
Server Component制限 | Client Componentに'use client' 追加 |
Cannot resolve workspace package |
Webpack alias設定不足 |
next.config.js のwebpack設定を確認 |
Type declaration not found |
TypeScript paths設定 |
tsconfig.json のpaths設定を確認 |
# 1. 必要なファイルが存在するか確認
ls -la next.config.js tsconfig.json tailwind.config.js
# 2. ワークスペースパッケージがビルドされているか確認
ls -la ../../dist/
# 3. 依存関係がインストールされているか確認
pnpm list @gftdcojp/ui
# 4. TypeScript型チェック
pnpm type-check
# 5. ビルドテスト
pnpm build
# 1. ワークスペースインストール
pnpm install
# 2. UIパッケージビルド
pnpm build
# 3. Vite環境でテスト
cd examples && pnpm dev
# 4. Next.js環境でテスト
cd examples/nextjs && pnpm dev
/** @type {import('next').NextConfig} */
const path = require('path');
const nextConfig = {
experimental: {
externalDir: true, // Allow imports from outside project directory
},
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
'@gftdcojp/ui': path.resolve(__dirname, '../../dist/index.es.js'),
'@gftdcojp/ui/styles': path.resolve(__dirname, '../../dist/styles.css'),
};
return config;
},
transpilePackages: ['@gftdcojp/ui'],
};
module.exports = nextConfig;
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@gftdcojp/ui": ["../../dist/index.d.ts"],
"@gftdcojp/ui/*": ["../../dist/*"]
}
},
"include": [
"../../src/**/*.ts",
"../../dist/**/*.d.ts"
]
}
// pages/_app.tsx
import '@gftdcojp/ui/styles';
import { Button, NotificationBanner } from '@gftdcojp/ui';
export default function App({ Component, pageProps }) {
return (
<div>
<NotificationBanner type="success">
Pages Router で正常に動作中!
</NotificationBanner>
<Component {...pageProps} />
</div>
);
}
// app/layout.tsx
import '@gftdcojp/ui/styles';
import { NotificationBanner } from '@gftdcojp/ui';
export default function RootLayout({ children }) {
return (
<html>
<body>
<NotificationBanner type="success">
App Router で正常に動作中!
</NotificationBanner>
{children}
</body>
</html>
);
}
// app/page.tsx
'use client';
import { Button, Input } from '@gftdcojp/ui';
export default function HomePage() {
return (
<div>
<Button variant="primary">Click me</Button>
<Input placeholder="Enter text" />
</div>
);
}