@einja/dev-cli 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +49 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +243 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +23 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/sync.d.ts +7 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +294 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/sync.test.d.ts +2 -0
- package/dist/commands/sync.test.d.ts.map +1 -0
- package/dist/commands/sync.test.js +593 -0
- package/dist/commands/sync.test.js.map +1 -0
- package/dist/commands/task-loop.d.ts +11 -0
- package/dist/commands/task-loop.d.ts.map +1 -0
- package/dist/commands/task-loop.js +81 -0
- package/dist/commands/task-loop.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/file-system.d.ts +39 -0
- package/dist/lib/file-system.d.ts.map +1 -0
- package/dist/lib/file-system.js +79 -0
- package/dist/lib/file-system.js.map +1 -0
- package/dist/lib/mcp-config.d.ts +43 -0
- package/dist/lib/mcp-config.d.ts.map +1 -0
- package/dist/lib/mcp-config.js +109 -0
- package/dist/lib/mcp-config.js.map +1 -0
- package/dist/lib/mcp-config.test.d.ts +2 -0
- package/dist/lib/mcp-config.test.d.ts.map +1 -0
- package/dist/lib/mcp-config.test.js +285 -0
- package/dist/lib/mcp-config.test.js.map +1 -0
- package/dist/lib/merger.d.ts +41 -0
- package/dist/lib/merger.d.ts.map +1 -0
- package/dist/lib/merger.js +164 -0
- package/dist/lib/merger.js.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.d.ts +35 -0
- package/dist/lib/preset-update/cli-repo-detector.d.ts.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.js +83 -0
- package/dist/lib/preset-update/cli-repo-detector.js.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.test.d.ts +2 -0
- package/dist/lib/preset-update/cli-repo-detector.test.d.ts.map +1 -0
- package/dist/lib/preset-update/cli-repo-detector.test.js +120 -0
- package/dist/lib/preset-update/cli-repo-detector.test.js.map +1 -0
- package/dist/lib/preset-update/file-copier.d.ts +59 -0
- package/dist/lib/preset-update/file-copier.d.ts.map +1 -0
- package/dist/lib/preset-update/file-copier.js +220 -0
- package/dist/lib/preset-update/file-copier.js.map +1 -0
- package/dist/lib/preset-update/file-copier.test.d.ts +2 -0
- package/dist/lib/preset-update/file-copier.test.d.ts.map +1 -0
- package/dist/lib/preset-update/file-copier.test.js +297 -0
- package/dist/lib/preset-update/file-copier.test.js.map +1 -0
- package/dist/lib/preset-update/preset-finder.d.ts +39 -0
- package/dist/lib/preset-update/preset-finder.d.ts.map +1 -0
- package/dist/lib/preset-update/preset-finder.js +92 -0
- package/dist/lib/preset-update/preset-finder.js.map +1 -0
- package/dist/lib/preset-update/preset-finder.test.d.ts +2 -0
- package/dist/lib/preset-update/preset-finder.test.d.ts.map +1 -0
- package/dist/lib/preset-update/preset-finder.test.js +128 -0
- package/dist/lib/preset-update/preset-finder.test.js.map +1 -0
- package/dist/lib/preset.d.ts +14 -0
- package/dist/lib/preset.d.ts.map +1 -0
- package/dist/lib/preset.js +52 -0
- package/dist/lib/preset.js.map +1 -0
- package/dist/lib/sync/backup-manager.d.ts +50 -0
- package/dist/lib/sync/backup-manager.d.ts.map +1 -0
- package/dist/lib/sync/backup-manager.js +117 -0
- package/dist/lib/sync/backup-manager.js.map +1 -0
- package/dist/lib/sync/backup-manager.test.d.ts +2 -0
- package/dist/lib/sync/backup-manager.test.d.ts.map +1 -0
- package/dist/lib/sync/backup-manager.test.js +155 -0
- package/dist/lib/sync/backup-manager.test.js.map +1 -0
- package/dist/lib/sync/batch-processor.d.ts +27 -0
- package/dist/lib/sync/batch-processor.d.ts.map +1 -0
- package/dist/lib/sync/batch-processor.js +46 -0
- package/dist/lib/sync/batch-processor.js.map +1 -0
- package/dist/lib/sync/batch-processor.test.d.ts +2 -0
- package/dist/lib/sync/batch-processor.test.d.ts.map +1 -0
- package/dist/lib/sync/batch-processor.test.js +110 -0
- package/dist/lib/sync/batch-processor.test.js.map +1 -0
- package/dist/lib/sync/category-validator.d.ts +36 -0
- package/dist/lib/sync/category-validator.d.ts.map +1 -0
- package/dist/lib/sync/category-validator.js +46 -0
- package/dist/lib/sync/category-validator.js.map +1 -0
- package/dist/lib/sync/category-validator.test.d.ts +2 -0
- package/dist/lib/sync/category-validator.test.d.ts.map +1 -0
- package/dist/lib/sync/category-validator.test.js +89 -0
- package/dist/lib/sync/category-validator.test.js.map +1 -0
- package/dist/lib/sync/conflict-reporter.d.ts +57 -0
- package/dist/lib/sync/conflict-reporter.d.ts.map +1 -0
- package/dist/lib/sync/conflict-reporter.js +81 -0
- package/dist/lib/sync/conflict-reporter.js.map +1 -0
- package/dist/lib/sync/conflict-reporter.test.d.ts +2 -0
- package/dist/lib/sync/conflict-reporter.test.d.ts.map +1 -0
- package/dist/lib/sync/conflict-reporter.test.js +132 -0
- package/dist/lib/sync/conflict-reporter.test.js.map +1 -0
- package/dist/lib/sync/diff-engine.d.ts +28 -0
- package/dist/lib/sync/diff-engine.d.ts.map +1 -0
- package/dist/lib/sync/diff-engine.js +118 -0
- package/dist/lib/sync/diff-engine.js.map +1 -0
- package/dist/lib/sync/diff-engine.test.d.ts +2 -0
- package/dist/lib/sync/diff-engine.test.d.ts.map +1 -0
- package/dist/lib/sync/diff-engine.test.js +133 -0
- package/dist/lib/sync/diff-engine.test.js.map +1 -0
- package/dist/lib/sync/file-filter.d.ts +40 -0
- package/dist/lib/sync/file-filter.d.ts.map +1 -0
- package/dist/lib/sync/file-filter.js +171 -0
- package/dist/lib/sync/file-filter.js.map +1 -0
- package/dist/lib/sync/file-filter.test.d.ts +2 -0
- package/dist/lib/sync/file-filter.test.d.ts.map +1 -0
- package/dist/lib/sync/file-filter.test.js +179 -0
- package/dist/lib/sync/file-filter.test.js.map +1 -0
- package/dist/lib/sync/hash-cache.d.ts +34 -0
- package/dist/lib/sync/hash-cache.d.ts.map +1 -0
- package/dist/lib/sync/hash-cache.js +51 -0
- package/dist/lib/sync/hash-cache.js.map +1 -0
- package/dist/lib/sync/hash-cache.test.d.ts +2 -0
- package/dist/lib/sync/hash-cache.test.d.ts.map +1 -0
- package/dist/lib/sync/hash-cache.test.js +110 -0
- package/dist/lib/sync/hash-cache.test.js.map +1 -0
- package/dist/lib/sync/integration.test.d.ts +2 -0
- package/dist/lib/sync/integration.test.d.ts.map +1 -0
- package/dist/lib/sync/integration.test.js +317 -0
- package/dist/lib/sync/integration.test.js.map +1 -0
- package/dist/lib/sync/marker-processor.d.ts +54 -0
- package/dist/lib/sync/marker-processor.d.ts.map +1 -0
- package/dist/lib/sync/marker-processor.js +208 -0
- package/dist/lib/sync/marker-processor.js.map +1 -0
- package/dist/lib/sync/marker-processor.test.d.ts +2 -0
- package/dist/lib/sync/marker-processor.test.d.ts.map +1 -0
- package/dist/lib/sync/marker-processor.test.js +245 -0
- package/dist/lib/sync/marker-processor.test.js.map +1 -0
- package/dist/lib/sync/metadata-manager.d.ts +46 -0
- package/dist/lib/sync/metadata-manager.d.ts.map +1 -0
- package/dist/lib/sync/metadata-manager.js +129 -0
- package/dist/lib/sync/metadata-manager.js.map +1 -0
- package/dist/lib/sync/metadata-manager.test.d.ts +2 -0
- package/dist/lib/sync/metadata-manager.test.d.ts.map +1 -0
- package/dist/lib/sync/metadata-manager.test.js +137 -0
- package/dist/lib/sync/metadata-manager.test.js.map +1 -0
- package/dist/lib/sync/performance.test.d.ts +2 -0
- package/dist/lib/sync/performance.test.d.ts.map +1 -0
- package/dist/lib/sync/performance.test.js +126 -0
- package/dist/lib/sync/performance.test.js.map +1 -0
- package/dist/types/index.d.ts +59 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/preset-update.d.ts +106 -0
- package/dist/types/preset-update.d.ts.map +1 -0
- package/dist/types/preset-update.js +5 -0
- package/dist/types/preset-update.js.map +1 -0
- package/dist/types/sync.d.ts +169 -0
- package/dist/types/sync.d.ts.map +1 -0
- package/dist/types/sync.js +19 -0
- package/dist/types/sync.js.map +1 -0
- package/package.json +72 -0
- package/presets/minimal/.claude/agents/einja/docs/docs-updater.md +161 -0
- package/presets/minimal/.claude/agents/einja/frontend/design-engineer.md +685 -0
- package/presets/minimal/.claude/agents/einja/frontend/frontend-architect.md +747 -0
- package/presets/minimal/.claude/agents/einja/frontend/frontend-coder.md +441 -0
- package/presets/minimal/.claude/agents/einja/git/conflict-resolver.md +148 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-design-generator.md +462 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-qa-generator.md +466 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-requirements-generator.md +416 -0
- package/presets/minimal/.claude/agents/einja/specs/spec-tasks-generator.md +608 -0
- package/presets/minimal/.claude/agents/einja/task/task-committer.md +82 -0
- package/presets/minimal/.claude/agents/einja/task/task-executer.md +352 -0
- package/presets/minimal/.claude/agents/einja/task/task-modification-analyzer.md +369 -0
- package/presets/minimal/.claude/agents/einja/task/task-qa.md +74 -0
- package/presets/minimal/.claude/agents/einja/task/task-reviewer.md +169 -0
- package/presets/minimal/.claude/commands/einja/frontend-implement.md +322 -0
- package/presets/minimal/.claude/commands/einja/spec-create.md +254 -0
- package/presets/minimal/.claude/commands/einja/start-dev.md +98 -0
- package/presets/minimal/.claude/commands/einja/sync-cursor-commands.md +203 -0
- package/presets/minimal/.claude/commands/einja/task-exec.md +390 -0
- package/presets/minimal/.claude/commands/einja/update-docs-by-task-specs.md +448 -0
- package/presets/minimal/.claude/hooks/einja/biome-format.sh +49 -0
- package/presets/minimal/.claude/hooks/einja/design-doc-check.sh +61 -0
- package/presets/minimal/.claude/hooks/einja/detect-secrets.sh +62 -0
- package/presets/minimal/.claude/hooks/einja/large-file-warning.sh +42 -0
- package/presets/minimal/.claude/hooks/einja/playwright-resize.sh +36 -0
- package/presets/minimal/.claude/hooks/einja/typecheck.sh +37 -0
- package/presets/minimal/.claude/hooks/einja/unset-volta-recursion.sh +32 -0
- package/presets/minimal/.claude/hooks/einja/validate-git-commit.sh +239 -0
- package/presets/minimal/.claude/hooks/einja/warn-index-ts.sh +34 -0
- package/presets/minimal/.claude/hooks/einja/warn-relative-import.sh +48 -0
- package/presets/minimal/.claude/settings.json +174 -0
- package/presets/minimal/.claude/skills/einja/api-development/SKILL.md +14 -0
- package/presets/minimal/.claude/skills/einja/backend-architecture/SKILL.md +14 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/SKILL.md +120 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/reference/naming-conventions.md +107 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/reference/prohibited-patterns.md +169 -0
- package/presets/minimal/.claude/skills/einja/coding-standards/reference/typescript-rules.md +247 -0
- package/presets/minimal/.claude/skills/einja/component-design/SKILL.md +109 -0
- package/presets/minimal/.claude/skills/einja/component-design/reference/directory-structure.md +117 -0
- package/presets/minimal/.claude/skills/einja/component-design/reference/props-patterns.md +159 -0
- package/presets/minimal/.claude/skills/einja/component-design/reference/styling-guide.md +200 -0
- package/presets/minimal/.claude/skills/einja/conflict-resolver/SKILL.md +190 -0
- package/presets/minimal/.claude/skills/einja/frontend-development/SKILL.md +14 -0
- package/presets/minimal/.claude/skills/einja/general-context-loader/SKILL.md +254 -0
- package/presets/minimal/.claude/skills/einja/output-format/SKILL.md +137 -0
- package/presets/minimal/.claude/skills/einja/spec-context-loader/SKILL.md +177 -0
- package/presets/minimal/.claude/skills/einja/task-commit/SKILL.md +269 -0
- package/presets/minimal/.claude/skills/einja/task-qa/SKILL.md +306 -0
- package/presets/minimal/.claude/skills/einja/task-qa/reference/failure-patterns.md +69 -0
- package/presets/minimal/.claude/skills/einja/task-qa/reference/troubleshooting.md +65 -0
- package/presets/minimal/.claude/skills/einja/task-qa/reference/usage-patterns.md +52 -0
- package/presets/minimal/.claude/skills/einja/task-qa/templates/qa-test-template.md +128 -0
- package/presets/minimal/preset.yaml +111 -0
- package/presets/minimal/symlinks.json +45 -0
- package/scaffolds/.mcp.json +45 -0
- package/scaffolds/CLAUDE.md.template +318 -0
- package/scaffolds/steering/README.md +170 -0
- package/scaffolds/steering/acceptance-criteria-and-qa-guide.md +415 -0
- package/scaffolds/steering/architecture.md +481 -0
- package/scaffolds/steering/branch-strategy.md +362 -0
- package/scaffolds/steering/commit-rules.md +217 -0
- package/scaffolds/steering/db-schema-design.md +609 -0
- package/scaffolds/steering/development/api-development.md +783 -0
- package/scaffolds/steering/development/backend-architecture.md +731 -0
- package/scaffolds/steering/development/frontend-development.md +1537 -0
- package/scaffolds/steering/development/review-guidelines.md +365 -0
- package/scaffolds/steering/development/testing-strategy.md +819 -0
- package/scaffolds/steering/development-workflow.md +429 -0
- package/scaffolds/steering/infrastructure/deployment.md +277 -0
- package/scaffolds/steering/infrastructure/environment-variables.md +298 -0
- package/scaffolds/steering/product.md +540 -0
- package/scaffolds/steering/task-management.md +367 -0
- package/templates/README.md +159 -0
- package/templates/design-simple.md.template +172 -0
- package/templates/design.md.template +327 -0
- package/templates/qa-test.md.template +125 -0
- package/templates/requirements.md.template +254 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Component Design Skill
|
|
2
|
+
|
|
3
|
+
name: "component-design"
|
|
4
|
+
description: "Reactコンポーネントの設計原則と実装ガイドライン"
|
|
5
|
+
invocation: "agent-requested"
|
|
6
|
+
version: "1.0.0"
|
|
7
|
+
|
|
8
|
+
## 概要
|
|
9
|
+
|
|
10
|
+
このSkillは、プロジェクトにおけるReactコンポーネントの設計原則と実装ガイドラインを提供します。
|
|
11
|
+
|
|
12
|
+
## 基本原則
|
|
13
|
+
|
|
14
|
+
### 1. 単一責任の原則
|
|
15
|
+
- 各コンポーネントは単一の機能・責任を持つ
|
|
16
|
+
- 複数の機能が必要な場合は、複数のコンポーネントに分割する
|
|
17
|
+
|
|
18
|
+
### 2. 再利用可能性
|
|
19
|
+
- プロジェクト全体で再利用可能なコンポーネントを作成する
|
|
20
|
+
- プロパティ(props)による柔軟なカスタマイズを可能にする
|
|
21
|
+
|
|
22
|
+
### 3. 型安全性
|
|
23
|
+
- TypeScriptの型定義を必須とする
|
|
24
|
+
- プロパティ、状態、イベントハンドラーは全て型定義する
|
|
25
|
+
|
|
26
|
+
### 4. Co-location(共存配置)
|
|
27
|
+
- 機能固有のコンポーネントは関連するページの近くに配置する
|
|
28
|
+
- `_components` ディレクトリを使用してページ固有のコンポーネントを管理する
|
|
29
|
+
- 複数のページで共有されるコンポーネントのみ `src/components/` に配置する
|
|
30
|
+
|
|
31
|
+
## 詳細ドキュメント
|
|
32
|
+
|
|
33
|
+
各カテゴリの詳細な規約は以下を参照してください:
|
|
34
|
+
|
|
35
|
+
- [ディレクトリ構造](./reference/directory-structure.md) - ファイル配置とディレクトリ設計
|
|
36
|
+
- [Props設計パターン](./reference/props-patterns.md) - Props設計とイベントハンドリング
|
|
37
|
+
- [スタイリングガイド](./reference/styling-guide.md) - Panda CSSを使用したスタイリング規約
|
|
38
|
+
|
|
39
|
+
## クイックリファレンス
|
|
40
|
+
|
|
41
|
+
### ディレクトリ構造
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
src/
|
|
45
|
+
├── components/
|
|
46
|
+
│ ├── ui/ # 基本的なUIコンポーネント
|
|
47
|
+
│ │ ├── Button/
|
|
48
|
+
│ │ ├── Input/
|
|
49
|
+
│ │ └── ...
|
|
50
|
+
│ └── shared/ # 共通コンポーネント(レイアウト含む)
|
|
51
|
+
│ ├── Header/
|
|
52
|
+
│ ├── Footer/
|
|
53
|
+
│ └── ...
|
|
54
|
+
└── app/
|
|
55
|
+
├── dashboard/
|
|
56
|
+
│ ├── page.tsx
|
|
57
|
+
│ └── _components/ # ページ固有のコンポーネント
|
|
58
|
+
│ ├── DashboardChart/
|
|
59
|
+
│ └── StatsCard/
|
|
60
|
+
└── ...
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### コンポーネント命名規則
|
|
64
|
+
|
|
65
|
+
- **ファイル名**: PascalCase(例: `Button.tsx`, `UserProfile.tsx`)
|
|
66
|
+
- **例外**: shadcn/uiコンポーネントはkebab-case(例: `button.tsx`)
|
|
67
|
+
|
|
68
|
+
### コンポーネントディレクトリ構造
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
ComponentName/
|
|
72
|
+
├── index.tsx # コンポーネント本体
|
|
73
|
+
└── styles.ts # Panda CSS スタイル定義(必要に応じて)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 基本的な型定義
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface ButtonProps {
|
|
80
|
+
children: React.ReactNode;
|
|
81
|
+
variant?: "primary" | "secondary" | "danger";
|
|
82
|
+
size?: "sm" | "md" | "lg";
|
|
83
|
+
disabled?: boolean;
|
|
84
|
+
onClick?: () => void;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## チェックリスト
|
|
89
|
+
|
|
90
|
+
新しいコンポーネントを作成する際の確認事項:
|
|
91
|
+
|
|
92
|
+
- [ ] 適切なディレクトリに配置されている
|
|
93
|
+
- [ ] TypeScript の型定義が完全
|
|
94
|
+
- [ ] Panda CSS でスタイリングされている
|
|
95
|
+
- [ ] プロパティのデフォルト値が設定されている
|
|
96
|
+
- [ ] アクセシビリティが考慮されている
|
|
97
|
+
- [ ] 単体テストが実装されている
|
|
98
|
+
|
|
99
|
+
## 関連Skill・ドキュメント
|
|
100
|
+
|
|
101
|
+
- [coding-standards](../coding-standards/SKILL.md) - コーディング規約
|
|
102
|
+
- `docs/einja/steering/development/testing-strategy.md` - テスト戦略
|
|
103
|
+
- `docs/einja/steering/development/frontend-development.md` - フロントエンド開発ガイド
|
|
104
|
+
|
|
105
|
+
## 参考資料
|
|
106
|
+
|
|
107
|
+
- [React 公式ドキュメント](https://react.dev)
|
|
108
|
+
- [TypeScript 公式ドキュメント](https://www.typescriptlang.org)
|
|
109
|
+
- [Panda CSS ドキュメント](https://panda-css.com)
|
package/presets/minimal/.claude/skills/einja/component-design/reference/directory-structure.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# ディレクトリ構造
|
|
2
|
+
|
|
3
|
+
## プロジェクト全体のコンポーネント配置
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
src/
|
|
7
|
+
├── components/
|
|
8
|
+
│ ├── ui/ # 基本的なUIコンポーネント
|
|
9
|
+
│ │ ├── Button/
|
|
10
|
+
│ │ ├── Input/
|
|
11
|
+
│ │ ├── Dialog/
|
|
12
|
+
│ │ └── ...
|
|
13
|
+
│ └── shared/ # 共通コンポーネント(レイアウト含む)
|
|
14
|
+
│ ├── Header/
|
|
15
|
+
│ ├── Footer/
|
|
16
|
+
│ ├── Sidebar/
|
|
17
|
+
│ ├── LoadingSpinner/
|
|
18
|
+
│ ├── ErrorBoundary/
|
|
19
|
+
│ └── ...
|
|
20
|
+
└── app/
|
|
21
|
+
├── dashboard/
|
|
22
|
+
│ ├── page.tsx
|
|
23
|
+
│ └── _components/ # ページ固有のコンポーネント (co-location)
|
|
24
|
+
│ ├── DashboardChart/
|
|
25
|
+
│ ├── StatsCard/
|
|
26
|
+
│ └── ...
|
|
27
|
+
├── auth/
|
|
28
|
+
│ ├── login/
|
|
29
|
+
│ │ ├── page.tsx
|
|
30
|
+
│ │ └── _components/
|
|
31
|
+
│ │ ├── LoginForm/
|
|
32
|
+
│ │ └── ...
|
|
33
|
+
│ └── register/
|
|
34
|
+
│ ├── page.tsx
|
|
35
|
+
│ └── _components/
|
|
36
|
+
│ ├── RegisterForm/
|
|
37
|
+
│ └── ...
|
|
38
|
+
└── ...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## コンポーネント配置のルール
|
|
42
|
+
|
|
43
|
+
### `src/components/ui/`
|
|
44
|
+
- shadcn/uiなどの基本的なUIコンポーネント
|
|
45
|
+
- 複数ページで使用される汎用コンポーネント
|
|
46
|
+
- Button、Input、Dialog、Cardなど
|
|
47
|
+
|
|
48
|
+
### `src/components/shared/`
|
|
49
|
+
- レイアウトコンポーネント(Header、Footer、Sidebar)
|
|
50
|
+
- 共通のユーティリティコンポーネント(LoadingSpinner、ErrorBoundary)
|
|
51
|
+
- 複数の機能領域で共有されるコンポーネント
|
|
52
|
+
|
|
53
|
+
### `app/*/page/_components/`
|
|
54
|
+
- ページ固有のコンポーネント
|
|
55
|
+
- Co-locationパターンに従った配置
|
|
56
|
+
- 他のページでは使用しないコンポーネント
|
|
57
|
+
|
|
58
|
+
## コンポーネントディレクトリ構造
|
|
59
|
+
|
|
60
|
+
### 基本構造
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
ComponentName/
|
|
64
|
+
├── index.tsx # コンポーネント本体
|
|
65
|
+
└── styles.ts # Panda CSS スタイル定義(必要に応じて)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 複雑なコンポーネントの場合
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
ComponentName/
|
|
72
|
+
├── index.tsx # メインエクスポート
|
|
73
|
+
├── ComponentName.tsx # コンポーネント本体
|
|
74
|
+
├── styles.ts # Panda CSS スタイル定義
|
|
75
|
+
├── types.ts # 型定義
|
|
76
|
+
├── hooks.ts # カスタムフック
|
|
77
|
+
└── ComponentName.test.tsx # テスト(co-location)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 命名規則
|
|
81
|
+
|
|
82
|
+
### ファイル名
|
|
83
|
+
- **PascalCase を使用**: `Button.tsx`, `UserProfile.tsx`
|
|
84
|
+
- **コンポーネント名とファイル名を一致させる**
|
|
85
|
+
|
|
86
|
+
### 例外:shadcn/ui
|
|
87
|
+
- shadcn/uiで生成されたコンポーネントはkebab-caseファイル名
|
|
88
|
+
- 例: `button.tsx`, `input.tsx`
|
|
89
|
+
- これらはそのまま使用し、新規作成するカスタムコンポーネントのみPascalCaseを適用
|
|
90
|
+
|
|
91
|
+
## Co-location パターン
|
|
92
|
+
|
|
93
|
+
### メリット
|
|
94
|
+
- 関連するコードが近くにある
|
|
95
|
+
- ファイルの検索が容易
|
|
96
|
+
- 機能削除時のクリーンアップが簡単
|
|
97
|
+
|
|
98
|
+
### 実践例
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
app/
|
|
102
|
+
└── users/
|
|
103
|
+
├── page.tsx
|
|
104
|
+
├── loading.tsx
|
|
105
|
+
├── error.tsx
|
|
106
|
+
└── _components/
|
|
107
|
+
├── UserList/
|
|
108
|
+
│ ├── index.tsx
|
|
109
|
+
│ └── UserListItem.tsx
|
|
110
|
+
└── UserSearchForm/
|
|
111
|
+
└── index.tsx
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `_components` の役割
|
|
115
|
+
- アンダースコアプレフィックスはNext.jsのルーティングから除外される
|
|
116
|
+
- ページ固有のコンポーネントを整理する場所
|
|
117
|
+
- 他のページでは使用しないコンポーネントを格納
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Props設計パターン
|
|
2
|
+
|
|
3
|
+
## 型定義
|
|
4
|
+
|
|
5
|
+
### Props インターフェース
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
interface ButtonProps {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
variant?: "primary" | "secondary" | "danger";
|
|
11
|
+
size?: "sm" | "md" | "lg";
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
onClick?: () => void;
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### デフォルトProps
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
const defaultProps: Partial<ButtonProps> = {
|
|
21
|
+
variant: "primary",
|
|
22
|
+
size: "md",
|
|
23
|
+
disabled: false,
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## イベントハンドリング
|
|
28
|
+
|
|
29
|
+
### 命名規則
|
|
30
|
+
- `on` + 動詞の命名規則を使用
|
|
31
|
+
- 例: `onClick`, `onSubmit`, `onChange`
|
|
32
|
+
|
|
33
|
+
### 型定義
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
interface FormProps {
|
|
37
|
+
onSubmit: (data: FormData) => void;
|
|
38
|
+
onChange: (field: string, value: string) => void;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 状態管理
|
|
43
|
+
|
|
44
|
+
### ローカル状態
|
|
45
|
+
- `useState` でローカル状態を管理
|
|
46
|
+
- 複雑な状態は `useReducer` を検討
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
50
|
+
|
|
51
|
+
// 複雑な状態の場合
|
|
52
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## エラーハンドリング
|
|
56
|
+
|
|
57
|
+
### Error Boundary
|
|
58
|
+
- 予期しないエラーをキャッチ
|
|
59
|
+
- ユーザーフレンドリーなエラー表示
|
|
60
|
+
|
|
61
|
+
### バリデーション
|
|
62
|
+
- フォーム入力のバリデーション
|
|
63
|
+
- 適切なエラーメッセージの表示
|
|
64
|
+
|
|
65
|
+
## 実装例
|
|
66
|
+
|
|
67
|
+
### 基本的なButtonコンポーネント
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// index.tsx
|
|
71
|
+
export interface ButtonProps {
|
|
72
|
+
children: React.ReactNode;
|
|
73
|
+
variant?: "primary" | "secondary" | "danger";
|
|
74
|
+
size?: "sm" | "md" | "lg";
|
|
75
|
+
disabled?: boolean;
|
|
76
|
+
onClick?: () => void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
import { button } from "styled-system/recipes";
|
|
80
|
+
import type { ButtonProps } from "./types";
|
|
81
|
+
|
|
82
|
+
export const Button: React.FC<ButtonProps> = ({
|
|
83
|
+
children,
|
|
84
|
+
variant = "primary",
|
|
85
|
+
size = "md",
|
|
86
|
+
disabled = false,
|
|
87
|
+
onClick,
|
|
88
|
+
}) => {
|
|
89
|
+
return (
|
|
90
|
+
<button
|
|
91
|
+
className={button({ variant, size })}
|
|
92
|
+
disabled={disabled}
|
|
93
|
+
onClick={onClick}
|
|
94
|
+
>
|
|
95
|
+
{children}
|
|
96
|
+
</button>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## パフォーマンス
|
|
102
|
+
|
|
103
|
+
### メモ化
|
|
104
|
+
- `React.memo` で不要な再レンダリングを防止
|
|
105
|
+
- `useMemo`, `useCallback` で計算結果をキャッシュ
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const MemoizedComponent = React.memo(({ data, onClick }) => {
|
|
109
|
+
return <div onClick={onClick}>{data.name}</div>;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// useCallbackでコールバックをメモ化
|
|
113
|
+
const handleClick = useCallback(() => {
|
|
114
|
+
// 処理
|
|
115
|
+
}, [dependency]);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 遅延読み込み
|
|
119
|
+
- `React.lazy` で大きなコンポーネントの遅延読み込み
|
|
120
|
+
- `Suspense` で読み込み状態を表示
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
|
|
124
|
+
|
|
125
|
+
function App() {
|
|
126
|
+
return (
|
|
127
|
+
<Suspense fallback={<Loading />}>
|
|
128
|
+
<HeavyComponent />
|
|
129
|
+
</Suspense>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## アクセシビリティ
|
|
135
|
+
|
|
136
|
+
### セマンティックHTML
|
|
137
|
+
- 適切なHTMLタグを使用
|
|
138
|
+
- `aria-*` 属性の適切な使用
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
<button
|
|
142
|
+
aria-label="メニューを開く"
|
|
143
|
+
aria-expanded={isOpen}
|
|
144
|
+
>
|
|
145
|
+
<MenuIcon />
|
|
146
|
+
</button>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### キーボード操作
|
|
150
|
+
- キーボードのみでの操作を可能にする
|
|
151
|
+
- フォーカス管理の実装
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
155
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
156
|
+
handleClick();
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
```
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# スタイリングガイド(Panda CSS)
|
|
2
|
+
|
|
3
|
+
## 基本的な使い方
|
|
4
|
+
|
|
5
|
+
### Panda CSS の使用
|
|
6
|
+
- Panda CSS を使用してスタイルを定義
|
|
7
|
+
- デザイントークンとレシピを活用
|
|
8
|
+
- 型安全なスタイル定義
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import { css } from "styled-system/css";
|
|
12
|
+
import { button } from "styled-system/recipes";
|
|
13
|
+
|
|
14
|
+
const buttonStyles = button({
|
|
15
|
+
variant: "primary",
|
|
16
|
+
size: "md",
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## レシピの使用
|
|
21
|
+
|
|
22
|
+
### 基本的なレシピ
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// ✅ Panda CSS レシピの使用
|
|
26
|
+
import { button } from 'styled-system/recipes';
|
|
27
|
+
|
|
28
|
+
export function Button({ variant, size, children }: ButtonProps) {
|
|
29
|
+
return (
|
|
30
|
+
<button className={button({ variant, size })}>
|
|
31
|
+
{children}
|
|
32
|
+
</button>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## css関数の使用
|
|
38
|
+
|
|
39
|
+
### インラインスタイル
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { css } from 'styled-system/css';
|
|
43
|
+
|
|
44
|
+
const customStyles = css({
|
|
45
|
+
padding: '1rem',
|
|
46
|
+
backgroundColor: 'blue.500',
|
|
47
|
+
_hover: {
|
|
48
|
+
backgroundColor: 'blue.600'
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 複雑なスタイル定義
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
const cardStyles = css({
|
|
57
|
+
display: 'flex',
|
|
58
|
+
flexDirection: 'column',
|
|
59
|
+
padding: '4',
|
|
60
|
+
borderRadius: 'lg',
|
|
61
|
+
boxShadow: 'md',
|
|
62
|
+
backgroundColor: 'white',
|
|
63
|
+
_dark: {
|
|
64
|
+
backgroundColor: 'gray.800',
|
|
65
|
+
},
|
|
66
|
+
'& > h2': {
|
|
67
|
+
fontSize: 'xl',
|
|
68
|
+
fontWeight: 'bold',
|
|
69
|
+
marginBottom: '2',
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## スタイルの分離
|
|
75
|
+
|
|
76
|
+
### 別ファイルへの分離
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// styles.ts
|
|
80
|
+
import { css } from 'styled-system/css';
|
|
81
|
+
|
|
82
|
+
export const containerStyles = css({
|
|
83
|
+
maxWidth: 'container.lg',
|
|
84
|
+
marginX: 'auto',
|
|
85
|
+
paddingX: '4',
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const headerStyles = css({
|
|
89
|
+
display: 'flex',
|
|
90
|
+
alignItems: 'center',
|
|
91
|
+
justifyContent: 'space-between',
|
|
92
|
+
height: '16',
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Component.tsx
|
|
98
|
+
import { containerStyles, headerStyles } from './styles';
|
|
99
|
+
|
|
100
|
+
export function Layout({ children }) {
|
|
101
|
+
return (
|
|
102
|
+
<div className={containerStyles}>
|
|
103
|
+
<header className={headerStyles}>
|
|
104
|
+
{/* ... */}
|
|
105
|
+
</header>
|
|
106
|
+
{children}
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## クラス名の結合
|
|
113
|
+
|
|
114
|
+
### cn(className)ユーティリティの使用
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { cn } from '@/lib/utils';
|
|
118
|
+
|
|
119
|
+
export function Card({ className, children }: CardProps) {
|
|
120
|
+
return (
|
|
121
|
+
<div className={cn('border rounded-lg p-4', className)}>
|
|
122
|
+
{children}
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 条件付きスタイル
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { css } from 'styled-system/css';
|
|
132
|
+
import { cn } from '@/lib/utils';
|
|
133
|
+
|
|
134
|
+
export function Button({ isActive, className }) {
|
|
135
|
+
return (
|
|
136
|
+
<button
|
|
137
|
+
className={cn(
|
|
138
|
+
css({ padding: '2', borderRadius: 'md' }),
|
|
139
|
+
isActive && css({ backgroundColor: 'blue.500', color: 'white' }),
|
|
140
|
+
className
|
|
141
|
+
)}
|
|
142
|
+
>
|
|
143
|
+
Click me
|
|
144
|
+
</button>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## レスポンシブデザイン
|
|
150
|
+
|
|
151
|
+
### ブレークポイント
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const responsiveStyles = css({
|
|
155
|
+
fontSize: 'sm',
|
|
156
|
+
padding: '2',
|
|
157
|
+
md: {
|
|
158
|
+
fontSize: 'base',
|
|
159
|
+
padding: '4',
|
|
160
|
+
},
|
|
161
|
+
lg: {
|
|
162
|
+
fontSize: 'lg',
|
|
163
|
+
padding: '6',
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### カスタムブレークポイント
|
|
169
|
+
- sm: 640px
|
|
170
|
+
- md: 768px
|
|
171
|
+
- lg: 1024px
|
|
172
|
+
- xl: 1280px
|
|
173
|
+
- 2xl: 1440px
|
|
174
|
+
|
|
175
|
+
## ダークモード対応
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const themedStyles = css({
|
|
179
|
+
backgroundColor: 'white',
|
|
180
|
+
color: 'gray.900',
|
|
181
|
+
_dark: {
|
|
182
|
+
backgroundColor: 'gray.900',
|
|
183
|
+
color: 'gray.100',
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## ベストプラクティス
|
|
189
|
+
|
|
190
|
+
### 1. デザイントークンの活用
|
|
191
|
+
- 直接の数値ではなくトークンを使用
|
|
192
|
+
- `padding: 4` は `padding: 1rem` に相当
|
|
193
|
+
|
|
194
|
+
### 2. レシピを優先
|
|
195
|
+
- 再利用可能なスタイルはレシピとして定義
|
|
196
|
+
- コンポーネント固有のスタイルのみcss()を使用
|
|
197
|
+
|
|
198
|
+
### 3. スタイルの一貫性
|
|
199
|
+
- プロジェクト全体で同じトークンを使用
|
|
200
|
+
- カラーパレット、スペーシングの統一
|