CodeConnect Design System

アーキテクチャ

CodeConnect Design Systemの技術スタック、アーキテクチャ設計、および設計判断について説明します。

技術スタック

デザインシステム (packages/design-system)

UI

  • React 19
  • TypeScript 5.7
  • Radix UI (Headless UI)

スタイリング

  • Tailwind CSS 4
  • CSS変数
  • class-variance-authority

ビルド

  • tsup (高速バンドラー)
  • style-dictionary 4.2

ドキュメント

  • Storybook 8
  • Astro 5

プロジェクト構成

packages/design-system/
├── src/
│ ├── components/ # UIコンポーネント
│ ├── styles/
│ ├── tokens/
│ └── index.ts
├── .storybook/
└── tsup.config.ts

コンポーネント設計原則

1. ディレクトリ構成

各コンポーネントは独自のディレクトリを持ちます:

Button/
├── Button.tsx # コンポーネント本体
├── useButton.tsx # カスタムフック(ロジック分離)
└── Button.stories.tsx # Storybook

重要な規則:

  • ❌ コンポーネントディレクトリ内で index.ts は使用禁止
  • ✅ パッケージルート (src/index.ts) のみ許可

2. コンポーネント実装パターン

すべてのコンポーネントは以下のパターンに従います:

Button/Button.tsx
import { forwardRef } from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { useButton } from './useButton'
export const buttonVariants = cva(/* バリアント定義 */)
export interface ButtonProps
extends HTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
const buttonProps = useButton(props)
return <button ref={ref} {...buttonProps} />
}
)
Button.displayName = 'Button'
Button/useButton.tsx
import { cn } from '../../utils/cn'
import { type ButtonProps, buttonVariants } from './Button'
export function useButton({ className, variant, size, ...props }: ButtonProps) {
return {
className: cn(buttonVariants({ variant, size, className })),
...props,
}
}

3. ロジック/UI分離

  • UI層 (Component.tsx): 表示のみ
  • ロジック層 (useComponent.tsx): スタイル、状態、副作用

4. class-variance-authority (CVA)

バリアント管理にCVAを使用:

export const buttonVariants = cva(
'base-classes', // 共通クラス
{
variants: {
variant: {
primary: 'primary-classes',
secondary: 'secondary-classes',
},
size: {
sm: 'small-classes',
md: 'medium-classes',
},
},
defaultVariants: {
variant: 'primary',
size: 'md',
},
}
)

デザイントークン管理

style-dictionary

すべてのデザイントークンはstyle-dictionaryで一元管理:

packages/design-tokens/tokens/colors.json
{
"color": {
"brand": {
"base": { "value": "#1c71b9" }
}
}
}

自動生成されるCSS変数:

/* 自動生成 */
:root {
--color-brand-base: #1c71b9;
}

Tailwind CSS 4の@themeディレクティブで参照:

/* app.css など */
@import "tailwindcss";
@import "@codeconnect-llc/design-system/styles";
@theme {
--color-brand: var(--color-brand-base);
}

Radix UI採用方針

なぜRadix UIか?

複雑なコンポーネントにはRadix UIを使用:

  • ✅ アクセシビリティが完璧に実装済み
  • ✅ キーボードナビゲーション対応
  • ✅ フォーカス管理
  • ✅ Headless(スタイルは自由)

採用コンポーネント

コンポーネントRadix UIパッケージ
Select@radix-ui/react-select
Checkbox@radix-ui/react-checkbox
RadioGroup@radix-ui/react-radio-group
Switch@radix-ui/react-switch
Dialog@radix-ui/react-dialog
Toast@radix-ui/react-toast
Tooltip@radix-ui/react-tooltip

自社実装コンポーネント

シンプルなコンポーネントは自社実装:

  • Button, Card, Typography
  • Input, Textarea
  • Badge, Divider
  • Box, Stack

モノレポ構成

pnpm Workspaces

すべてのパッケージを効率的に管理:

pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'

依存関係

{
"dependencies": {
"@codeconnect-llc/design-system": "workspace:*"
}
}

ビルドシステム

tsup

高速なTypeScriptバンドラー:

tsup.config.ts
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
})

style-dictionary

トークン生成:

Terminal window
pnpm --filter @codeconnect/design-tokens build

出力:

  • build/web/tokens.css - CSS変数
  • build/ts/tokens.ts - TypeScript定数
  • build/native/tokens.ts - React Native用

開発ツール

Biome

Linter & Formatter:

  • シングルクォート
  • セミコロンなし
  • スペース2つインデント
  • 行幅100文字

TypeScript

Strict Mode有効:

{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true
}
}

設計判断の理由

なぜTailwind CSS 4?

  • デザイントークンとの統合
  • CSS変数ネイティブサポート
  • ビルド時の最適化
  • 開発体験の向上

パフォーマンス

バンドルサイズ最適化

  • Tree-shaking対応
  • ESM/CJS両対応
  • 個別コンポーネントインポート可能

ランタイムパフォーマンス

  • React 19の最新機能
  • memo化の適切な使用
  • レンダリング最適化

今後の展開

Phase 3: CMS統合

  • Sanity CMS導入
  • コンテンツ管理の柔軟化

Phase 4: 機能追加

  • 検索機能
  • 多言語対応
  • ダークモード

参考リンク