@einja/dev-cli 0.1.39 → 0.1.41
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 +89 -1
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +71 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +187 -13
- package/dist/commands/sync.js.map +1 -1
- package/dist/lib/dependency-checker.d.ts.map +1 -1
- package/dist/lib/merger.d.ts +12 -0
- package/dist/lib/merger.d.ts.map +1 -1
- package/dist/lib/merger.js +28 -0
- package/dist/lib/merger.js.map +1 -1
- package/dist/lib/preset-update/cli-repo-detector.d.ts.map +1 -1
- package/dist/lib/preset-update/file-copier.d.ts.map +1 -1
- package/dist/lib/preset-update/preset-finder.d.ts.map +1 -1
- package/dist/lib/preset.d.ts.map +1 -1
- package/dist/lib/sync/category-validator.d.ts +1 -1
- package/dist/lib/sync/category-validator.d.ts.map +1 -1
- package/dist/lib/sync/category-validator.js +2 -1
- package/dist/lib/sync/category-validator.js.map +1 -1
- package/dist/lib/sync/category-validator.test.js +3 -1
- package/dist/lib/sync/category-validator.test.js.map +1 -1
- package/dist/lib/sync/conflict-reporter.d.ts.map +1 -1
- package/dist/lib/sync/diff-engine.d.ts.map +1 -1
- package/dist/lib/sync/file-filter.d.ts.map +1 -1
- package/dist/lib/sync/file-filter.js +1 -0
- package/dist/lib/sync/file-filter.js.map +1 -1
- package/dist/lib/sync/integration.test.js +255 -69
- package/dist/lib/sync/integration.test.js.map +1 -1
- package/dist/lib/sync/json-processor.d.ts +4 -4
- package/dist/lib/sync/json-processor.d.ts.map +1 -1
- package/dist/lib/sync/json-processor.js +11 -11
- package/dist/lib/sync/json-processor.js.map +1 -1
- package/dist/lib/sync/marker-processor.d.ts +60 -8
- package/dist/lib/sync/marker-processor.d.ts.map +1 -1
- package/dist/lib/sync/marker-processor.js +117 -26
- package/dist/lib/sync/marker-processor.js.map +1 -1
- package/dist/lib/sync/marker-processor.test.js +261 -40
- package/dist/lib/sync/marker-processor.test.js.map +1 -1
- package/dist/lib/sync/metadata-manager.d.ts +4 -0
- package/dist/lib/sync/metadata-manager.d.ts.map +1 -1
- package/dist/lib/sync/metadata-manager.js +15 -0
- package/dist/lib/sync/metadata-manager.js.map +1 -1
- package/dist/lib/sync/metadata-manager.test.js +68 -0
- package/dist/lib/sync/metadata-manager.test.js.map +1 -1
- package/dist/lib/sync/orphan-cleaner.d.ts +29 -0
- package/dist/lib/sync/orphan-cleaner.d.ts.map +1 -0
- package/dist/lib/sync/orphan-cleaner.js +80 -0
- package/dist/lib/sync/orphan-cleaner.js.map +1 -0
- package/dist/lib/sync/orphan-cleaner.test.d.ts +2 -0
- package/dist/lib/sync/orphan-cleaner.test.d.ts.map +1 -0
- package/dist/lib/sync/orphan-cleaner.test.js +169 -0
- package/dist/lib/sync/orphan-cleaner.test.js.map +1 -0
- package/dist/lib/sync/project-private-synchronizer.d.ts +52 -0
- package/dist/lib/sync/project-private-synchronizer.d.ts.map +1 -0
- package/dist/lib/sync/project-private-synchronizer.js +106 -0
- package/dist/lib/sync/project-private-synchronizer.js.map +1 -0
- package/dist/lib/sync/project-private-synchronizer.test.d.ts +2 -0
- package/dist/lib/sync/project-private-synchronizer.test.d.ts.map +1 -0
- package/dist/lib/sync/project-private-synchronizer.test.js +348 -0
- package/dist/lib/sync/project-private-synchronizer.test.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/sync.d.ts +36 -6
- package/dist/types/sync.d.ts.map +1 -1
- package/dist/types/sync.js +2 -2
- package/dist/types/sync.js.map +1 -1
- package/package.json +5 -4
- package/presets/default/.claude/agents/einja/Explore.md +140 -0
- package/presets/default/.claude/agents/einja/backend-architect.md +4 -0
- package/presets/default/.claude/agents/einja/codex-agent.md +4 -0
- package/presets/default/.claude/agents/einja/design-engineer.md +4 -0
- package/presets/default/.claude/agents/einja/docs/docs-updater.md +4 -0
- package/presets/default/.claude/agents/einja/frontend-architect.md +4 -0
- package/presets/default/.claude/agents/einja/frontend-coder.md +4 -0
- package/presets/default/.claude/agents/einja/git/conflict-resolver.md +4 -0
- package/presets/default/.claude/agents/einja/specs/spec-design-generator.md +4 -1
- package/presets/default/.claude/agents/einja/specs/spec-qa-generator.md +4 -0
- package/presets/default/.claude/agents/einja/specs/spec-requirements-generator.md +4 -1
- package/presets/default/.claude/agents/einja/specs/spec-tasks-generator.md +6 -2
- package/presets/default/.claude/agents/einja/specs/spec-tasks-validator.md +4 -0
- package/presets/default/.claude/agents/einja/task/task-executer.md +57 -115
- package/presets/default/.claude/agents/einja/task/task-modification-analyzer.md +4 -0
- package/presets/default/.claude/agents/einja/task/task-qa.md +4 -0
- package/presets/default/.claude/agents/einja/task/task-reviewer.md +4 -0
- package/presets/default/.claude/commands/einja/einja-sync.md +5 -1
- package/presets/default/.claude/commands/einja/frontend-implement.md +3 -1
- package/presets/default/.claude/commands/einja/issue-exec.md +403 -0
- package/presets/default/.claude/commands/einja/spec-create.md +15 -1
- package/presets/default/.claude/commands/einja/start-dev.md +4 -0
- package/presets/default/.claude/commands/einja/sync-cursor-commands.md +4 -0
- package/presets/default/.claude/commands/einja/task-exec.md +106 -14
- package/presets/default/.claude/commands/einja/update-docs-by-task-specs.md +4 -0
- package/presets/default/.claude/hooks/einja/plan-mode-skill-loader.sh +23 -0
- package/presets/default/.claude/settings.json +15 -1
- package/presets/default/.claude/skills/einja-conflict-resolver/SKILL.md +4 -0
- package/presets/default/.claude/skills/einja-general-context-loader/SKILL.md +4 -0
- package/presets/default/.claude/skills/einja-output-format/SKILL.md +4 -0
- package/presets/default/.claude/skills/einja-project-overview/SKILL.md +7 -3
- package/presets/default/.claude/skills/einja-skill-creator/SKILL.md +266 -274
- package/presets/default/.claude/skills/einja-skill-creator/agents/analyzer.md +274 -0
- package/presets/default/.claude/skills/einja-skill-creator/agents/comparator.md +202 -0
- package/presets/default/.claude/skills/einja-skill-creator/agents/grader.md +195 -0
- package/presets/default/.claude/skills/einja-skill-creator/assets/eval_review.html +146 -0
- package/presets/default/.claude/skills/einja-skill-creator/eval-viewer/generate_review.py +471 -0
- package/presets/default/.claude/skills/einja-skill-creator/eval-viewer/viewer.html +1325 -0
- package/presets/default/.claude/skills/einja-skill-creator/references/schemas.md +430 -0
- package/presets/default/.claude/skills/einja-skill-creator/scripts/aggregate_benchmark.py +154 -0
- package/presets/default/.claude/skills/einja-skill-creator/scripts/generate_report.py +265 -0
- package/presets/default/.claude/skills/einja-skill-creator/scripts/improve_description.py +252 -0
- package/presets/default/.claude/skills/einja-skill-creator/scripts/init_skill.py +13 -19
- package/presets/default/.claude/skills/einja-skill-creator/scripts/package_skill.py +36 -7
- package/presets/default/.claude/skills/einja-skill-creator/scripts/run_eval.py +310 -0
- package/presets/default/.claude/skills/einja-skill-creator/scripts/run_loop.py +295 -0
- package/presets/default/.claude/skills/einja-skill-creator/scripts/utils.py +48 -0
- package/presets/default/.claude/skills/einja-spec-context-loader/SKILL.md +4 -0
- package/presets/default/.claude/skills/einja-task-commit/SKILL.md +4 -0
- package/presets/default/.claude/skills/einja-task-qa/SKILL.md +4 -0
- package/presets/default/.envrc +5 -0
- package/presets/default/.mcp.json +2 -12
- package/presets/default/CLAUDE.md.template +26 -4
- package/presets/default/docs/einja/example/specs/issues/issue999-example-task/tasks.md +1 -1
- package/presets/default/docs/einja/instructions/deployment-setup.md +3 -8
- package/presets/default/docs/einja/instructions/environment-setup.md +3 -8
- package/presets/default/docs/einja/instructions/issue-exec-workflow.md +276 -0
- package/presets/default/docs/einja/instructions/local-server-environment-and-worktree.md +70 -8
- package/presets/default/docs/einja/instructions/neon-cli-reference.md +3 -8
- package/presets/default/docs/einja/instructions/task-execute.md +23 -28
- package/presets/default/docs/einja/instructions/vercel-cli-reference.md +17 -10
- package/presets/default/docs/einja/steering/README.md +11 -11
- package/presets/default/docs/einja/steering/acceptance-criteria-and-qa-guide.md +3 -8
- package/presets/default/docs/einja/steering/architecture.md +3 -8
- package/presets/default/docs/einja/steering/branch-strategy.md +63 -70
- package/presets/default/docs/einja/steering/commit-rules.md +3 -8
- package/presets/default/docs/einja/steering/db-schema-design.md +3 -8
- package/presets/default/docs/einja/steering/development/api-development.md +3 -8
- package/presets/default/docs/einja/steering/development/backend-architecture.md +3 -8
- package/presets/default/docs/einja/steering/development/coding-standards.md +723 -0
- package/presets/default/docs/einja/steering/development/component-design.md +502 -0
- package/presets/default/docs/einja/steering/development/database-guidelines.md +54 -5
- package/presets/default/docs/einja/steering/development/frontend-development.md +3 -8
- package/presets/default/docs/einja/steering/development/playwright-guidelines.md +59 -0
- package/presets/default/docs/einja/steering/development/review-guidelines.md +3 -8
- package/presets/default/docs/einja/steering/development/testing-strategy.md +3 -8
- package/presets/default/docs/einja/steering/development-workflow.md +71 -124
- package/presets/default/docs/einja/steering/infrastructure/deployment.md +49 -55
- package/presets/default/docs/einja/steering/infrastructure/environment-variables.md +4 -8
- package/presets/default/docs/einja/steering/product.md +3 -8
- package/presets/default/docs/einja/steering/task-management.md +14 -98
- package/presets/default/scripts/ensure-serena.sh +75 -0
- package/presets/default/scripts/env-rotate-secrets.ts +336 -0
- package/presets/default/scripts/env-show.ts +130 -0
- package/presets/default/scripts/env.ts +479 -0
- package/presets/default/scripts/init.sh +92 -0
- package/presets/default/scripts/lib/env-common.ts +108 -0
- package/presets/default/scripts/lib/worktree-config.ts +64 -0
- package/presets/default/scripts/setup-dev.ts +640 -0
- package/presets/default/scripts/stop-serena.sh +25 -0
- package/presets/default/scripts/worktree/dev.ts +872 -0
- package/dist/lib/sync/seed-synchronizer.d.ts +0 -27
- package/dist/lib/sync/seed-synchronizer.d.ts.map +0 -1
- package/dist/lib/sync/seed-synchronizer.js +0 -72
- package/dist/lib/sync/seed-synchronizer.js.map +0 -1
- package/dist/lib/sync/seed-synchronizer.test.d.ts +0 -2
- package/dist/lib/sync/seed-synchronizer.test.d.ts.map +0 -1
- package/dist/lib/sync/seed-synchronizer.test.js +0 -147
- package/dist/lib/sync/seed-synchronizer.test.js.map +0 -1
- package/presets/default/.claude/skills/einja-api-development/SKILL.md +0 -14
- package/presets/default/.claude/skills/einja-backend-architecture/SKILL.md +0 -18
- package/presets/default/.claude/skills/einja-coding-standards/SKILL.md +0 -132
- package/presets/default/.claude/skills/einja-coding-standards/references/import-conventions.md +0 -69
- package/presets/default/.claude/skills/einja-coding-standards/references/naming-conventions.md +0 -107
- package/presets/default/.claude/skills/einja-coding-standards/references/prohibited-patterns.md +0 -169
- package/presets/default/.claude/skills/einja-coding-standards/references/typescript-rules.md +0 -247
- package/presets/default/.claude/skills/einja-component-design/SKILL.md +0 -109
- package/presets/default/.claude/skills/einja-component-design/references/directory-structure.md +0 -117
- package/presets/default/.claude/skills/einja-component-design/references/props-patterns.md +0 -159
- package/presets/default/.claude/skills/einja-component-design/references/styling-guide.md +0 -122
- package/presets/default/.claude/skills/einja-frontend-development/SKILL.md +0 -14
- package/presets/default/docs/einja/instructions/task-vibe-kanban-loop.md +0 -565
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
<!-- @einja:managed -->
|
|
2
|
+
# コンポーネント設計ガイドライン
|
|
3
|
+
|
|
4
|
+
## 概要
|
|
5
|
+
|
|
6
|
+
このドキュメントは、プロジェクトにおけるReactコンポーネントの設計原則と実装ガイドラインを提供します。
|
|
7
|
+
|
|
8
|
+
## 基本原則
|
|
9
|
+
|
|
10
|
+
### 1. 単一責任の原則
|
|
11
|
+
- 各コンポーネントは単一の機能・責任を持つ
|
|
12
|
+
- 複数の機能が必要な場合は、複数のコンポーネントに分割する
|
|
13
|
+
|
|
14
|
+
### 2. 再利用可能性
|
|
15
|
+
- プロジェクト全体で再利用可能なコンポーネントを作成する
|
|
16
|
+
- プロパティ(props)による柔軟なカスタマイズを可能にする
|
|
17
|
+
|
|
18
|
+
### 3. 型安全性
|
|
19
|
+
- TypeScriptの型定義を必須とする
|
|
20
|
+
- プロパティ、状態、イベントハンドラーは全て型定義する
|
|
21
|
+
|
|
22
|
+
### 4. Co-location(共存配置)
|
|
23
|
+
- 機能固有のコンポーネントは関連するページの近くに配置する
|
|
24
|
+
- `_components` ディレクトリを使用してページ固有のコンポーネントを管理する
|
|
25
|
+
- 複数のページで共有されるコンポーネントのみ `src/components/` に配置する
|
|
26
|
+
|
|
27
|
+
## クイックリファレンス
|
|
28
|
+
|
|
29
|
+
### ディレクトリ構造
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
src/
|
|
33
|
+
├── components/
|
|
34
|
+
│ ├── ui/ # 基本的なUIコンポーネント
|
|
35
|
+
│ │ ├── Button/
|
|
36
|
+
│ │ ├── Input/
|
|
37
|
+
│ │ └── ...
|
|
38
|
+
│ └── shared/ # 共通コンポーネント(レイアウト含む)
|
|
39
|
+
│ ├── Header/
|
|
40
|
+
│ ├── Footer/
|
|
41
|
+
│ └── ...
|
|
42
|
+
└── app/
|
|
43
|
+
├── dashboard/
|
|
44
|
+
│ ├── page.tsx
|
|
45
|
+
│ └── _components/ # ページ固有のコンポーネント
|
|
46
|
+
│ ├── DashboardChart/
|
|
47
|
+
│ └── StatsCard/
|
|
48
|
+
└── ...
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### コンポーネント命名規則
|
|
52
|
+
|
|
53
|
+
- **ファイル名**: PascalCase(例: `Button.tsx`, `UserProfile.tsx`)
|
|
54
|
+
- **例外**: shadcn/uiコンポーネントはkebab-case(例: `button.tsx`)
|
|
55
|
+
|
|
56
|
+
### コンポーネントディレクトリ構造
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
ComponentName/
|
|
60
|
+
├── index.tsx # コンポーネント本体
|
|
61
|
+
└── variants.ts # cvaバリアント定義(必要に応じて)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 基本的な型定義
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
interface ButtonProps {
|
|
68
|
+
children: React.ReactNode;
|
|
69
|
+
variant?: "primary" | "secondary" | "danger";
|
|
70
|
+
size?: "sm" | "md" | "lg";
|
|
71
|
+
disabled?: boolean;
|
|
72
|
+
onClick?: () => void;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## チェックリスト
|
|
77
|
+
|
|
78
|
+
新しいコンポーネントを作成する際の確認事項:
|
|
79
|
+
|
|
80
|
+
- [ ] 適切なディレクトリに配置されている
|
|
81
|
+
- [ ] TypeScript の型定義が完全
|
|
82
|
+
- [ ] Tailwind CSS でスタイリングされている
|
|
83
|
+
- [ ] プロパティのデフォルト値が設定されている
|
|
84
|
+
- [ ] アクセシビリティが考慮されている
|
|
85
|
+
- [ ] 単体テストが実装されている
|
|
86
|
+
|
|
87
|
+
## ディレクトリ構造
|
|
88
|
+
|
|
89
|
+
### プロジェクト全体のコンポーネント配置
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
src/
|
|
93
|
+
├── components/
|
|
94
|
+
│ ├── ui/ # 基本的なUIコンポーネント
|
|
95
|
+
│ │ ├── Button/
|
|
96
|
+
│ │ ├── Input/
|
|
97
|
+
│ │ ├── Dialog/
|
|
98
|
+
│ │ └── ...
|
|
99
|
+
│ └── shared/ # 共通コンポーネント(レイアウト含む)
|
|
100
|
+
│ ├── Header/
|
|
101
|
+
│ ├── Footer/
|
|
102
|
+
│ ├── Sidebar/
|
|
103
|
+
│ ├── LoadingSpinner/
|
|
104
|
+
│ ├── ErrorBoundary/
|
|
105
|
+
│ └── ...
|
|
106
|
+
└── app/
|
|
107
|
+
├── dashboard/
|
|
108
|
+
│ ├── page.tsx
|
|
109
|
+
│ └── _components/ # ページ固有のコンポーネント (co-location)
|
|
110
|
+
│ ├── DashboardChart/
|
|
111
|
+
│ ├── StatsCard/
|
|
112
|
+
│ └── ...
|
|
113
|
+
├── auth/
|
|
114
|
+
│ ├── login/
|
|
115
|
+
│ │ ├── page.tsx
|
|
116
|
+
│ │ └── _components/
|
|
117
|
+
│ │ ├── LoginForm/
|
|
118
|
+
│ │ └── ...
|
|
119
|
+
│ └── register/
|
|
120
|
+
│ ├── page.tsx
|
|
121
|
+
│ └── _components/
|
|
122
|
+
│ ├── RegisterForm/
|
|
123
|
+
│ └── ...
|
|
124
|
+
└── ...
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### コンポーネント配置のルール
|
|
128
|
+
|
|
129
|
+
#### `src/components/ui/`
|
|
130
|
+
- shadcn/uiなどの基本的なUIコンポーネント
|
|
131
|
+
- 複数ページで使用される汎用コンポーネント
|
|
132
|
+
- Button、Input、Dialog、Cardなど
|
|
133
|
+
|
|
134
|
+
#### `src/components/shared/`
|
|
135
|
+
- レイアウトコンポーネント(Header、Footer、Sidebar)
|
|
136
|
+
- 共通のユーティリティコンポーネント(LoadingSpinner、ErrorBoundary)
|
|
137
|
+
- 複数の機能領域で共有されるコンポーネント
|
|
138
|
+
|
|
139
|
+
#### `app/*/page/_components/`
|
|
140
|
+
- ページ固有のコンポーネント
|
|
141
|
+
- Co-locationパターンに従った配置
|
|
142
|
+
- 他のページでは使用しないコンポーネント
|
|
143
|
+
|
|
144
|
+
### コンポーネントディレクトリ構造
|
|
145
|
+
|
|
146
|
+
#### 基本構造
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
ComponentName/
|
|
150
|
+
├── index.tsx # コンポーネント本体
|
|
151
|
+
└── styles.ts # Panda CSS スタイル定義(必要に応じて)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### 複雑なコンポーネントの場合
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
ComponentName/
|
|
158
|
+
├── index.tsx # メインエクスポート
|
|
159
|
+
├── ComponentName.tsx # コンポーネント本体
|
|
160
|
+
├── styles.ts # Panda CSS スタイル定義
|
|
161
|
+
├── types.ts # 型定義
|
|
162
|
+
├── hooks.ts # カスタムフック
|
|
163
|
+
└── ComponentName.test.tsx # テスト(co-location)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 命名規則
|
|
167
|
+
|
|
168
|
+
#### ファイル名
|
|
169
|
+
- **PascalCase を使用**: `Button.tsx`, `UserProfile.tsx`
|
|
170
|
+
- **コンポーネント名とファイル名を一致させる**
|
|
171
|
+
|
|
172
|
+
#### 例外:shadcn/ui
|
|
173
|
+
- shadcn/uiで生成されたコンポーネントはkebab-caseファイル名
|
|
174
|
+
- 例: `button.tsx`, `input.tsx`
|
|
175
|
+
- これらはそのまま使用し、新規作成するカスタムコンポーネントのみPascalCaseを適用
|
|
176
|
+
|
|
177
|
+
### Co-location パターン
|
|
178
|
+
|
|
179
|
+
#### メリット
|
|
180
|
+
- 関連するコードが近くにある
|
|
181
|
+
- ファイルの検索が容易
|
|
182
|
+
- 機能削除時のクリーンアップが簡単
|
|
183
|
+
|
|
184
|
+
#### 実践例
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
app/
|
|
188
|
+
└── users/
|
|
189
|
+
├── page.tsx
|
|
190
|
+
├── loading.tsx
|
|
191
|
+
├── error.tsx
|
|
192
|
+
└── _components/
|
|
193
|
+
├── UserList/
|
|
194
|
+
│ ├── index.tsx
|
|
195
|
+
│ └── UserListItem.tsx
|
|
196
|
+
└── UserSearchForm/
|
|
197
|
+
└── index.tsx
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### `_components` の役割
|
|
201
|
+
- アンダースコアプレフィックスはNext.jsのルーティングから除外される
|
|
202
|
+
- ページ固有のコンポーネントを整理する場所
|
|
203
|
+
- 他のページでは使用しないコンポーネントを格納
|
|
204
|
+
|
|
205
|
+
## Props設計パターン
|
|
206
|
+
|
|
207
|
+
### 型定義
|
|
208
|
+
|
|
209
|
+
#### Props インターフェース
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
interface ButtonProps {
|
|
213
|
+
children: React.ReactNode;
|
|
214
|
+
variant?: "primary" | "secondary" | "danger";
|
|
215
|
+
size?: "sm" | "md" | "lg";
|
|
216
|
+
disabled?: boolean;
|
|
217
|
+
onClick?: () => void;
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### デフォルトProps
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
const defaultProps: Partial<ButtonProps> = {
|
|
225
|
+
variant: "primary",
|
|
226
|
+
size: "md",
|
|
227
|
+
disabled: false,
|
|
228
|
+
};
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### イベントハンドリング
|
|
232
|
+
|
|
233
|
+
#### 命名規則
|
|
234
|
+
- `on` + 動詞の命名規則を使用
|
|
235
|
+
- 例: `onClick`, `onSubmit`, `onChange`
|
|
236
|
+
|
|
237
|
+
#### 型定義
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
interface FormProps {
|
|
241
|
+
onSubmit: (data: FormData) => void;
|
|
242
|
+
onChange: (field: string, value: string) => void;
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 状態管理
|
|
247
|
+
|
|
248
|
+
#### ローカル状態
|
|
249
|
+
- `useState` でローカル状態を管理
|
|
250
|
+
- 複雑な状態は `useReducer` を検討
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
254
|
+
|
|
255
|
+
// 複雑な状態の場合
|
|
256
|
+
const [state, dispatch] = useReducer(reducer, initialState);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### エラーハンドリング
|
|
260
|
+
|
|
261
|
+
#### Error Boundary
|
|
262
|
+
- 予期しないエラーをキャッチ
|
|
263
|
+
- ユーザーフレンドリーなエラー表示
|
|
264
|
+
|
|
265
|
+
#### バリデーション
|
|
266
|
+
- フォーム入力のバリデーション
|
|
267
|
+
- 適切なエラーメッセージの表示
|
|
268
|
+
|
|
269
|
+
### 実装例
|
|
270
|
+
|
|
271
|
+
#### 基本的なButtonコンポーネント
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
// index.tsx
|
|
275
|
+
export interface ButtonProps {
|
|
276
|
+
children: React.ReactNode;
|
|
277
|
+
variant?: "primary" | "secondary" | "danger";
|
|
278
|
+
size?: "sm" | "md" | "lg";
|
|
279
|
+
disabled?: boolean;
|
|
280
|
+
onClick?: () => void;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
import { button } from "styled-system/recipes";
|
|
284
|
+
import type { ButtonProps } from "./types";
|
|
285
|
+
|
|
286
|
+
export const Button: React.FC<ButtonProps> = ({
|
|
287
|
+
children,
|
|
288
|
+
variant = "primary",
|
|
289
|
+
size = "md",
|
|
290
|
+
disabled = false,
|
|
291
|
+
onClick,
|
|
292
|
+
}) => {
|
|
293
|
+
return (
|
|
294
|
+
<button
|
|
295
|
+
className={button({ variant, size })}
|
|
296
|
+
disabled={disabled}
|
|
297
|
+
onClick={onClick}
|
|
298
|
+
>
|
|
299
|
+
{children}
|
|
300
|
+
</button>
|
|
301
|
+
);
|
|
302
|
+
};
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### パフォーマンス
|
|
306
|
+
|
|
307
|
+
#### メモ化
|
|
308
|
+
- `React.memo` で不要な再レンダリングを防止
|
|
309
|
+
- `useMemo`, `useCallback` で計算結果をキャッシュ
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
const MemoizedComponent = React.memo(({ data, onClick }) => {
|
|
313
|
+
return <div onClick={onClick}>{data.name}</div>;
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// useCallbackでコールバックをメモ化
|
|
317
|
+
const handleClick = useCallback(() => {
|
|
318
|
+
// 処理
|
|
319
|
+
}, [dependency]);
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### 遅延読み込み
|
|
323
|
+
- `React.lazy` で大きなコンポーネントの遅延読み込み
|
|
324
|
+
- `Suspense` で読み込み状態を表示
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
|
|
328
|
+
|
|
329
|
+
function App() {
|
|
330
|
+
return (
|
|
331
|
+
<Suspense fallback={<Loading />}>
|
|
332
|
+
<HeavyComponent />
|
|
333
|
+
</Suspense>
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### アクセシビリティ
|
|
339
|
+
|
|
340
|
+
#### セマンティックHTML
|
|
341
|
+
- 適切なHTMLタグを使用
|
|
342
|
+
- `aria-*` 属性の適切な使用
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
<button
|
|
346
|
+
aria-label="メニューを開く"
|
|
347
|
+
aria-expanded={isOpen}
|
|
348
|
+
>
|
|
349
|
+
<MenuIcon />
|
|
350
|
+
</button>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
#### キーボード操作
|
|
354
|
+
- キーボードのみでの操作を可能にする
|
|
355
|
+
- フォーカス管理の実装
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
359
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
360
|
+
handleClick();
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## スタイリングガイド(Tailwind CSS)
|
|
366
|
+
|
|
367
|
+
### 基本的な使い方
|
|
368
|
+
|
|
369
|
+
#### Tailwind CSS の使用
|
|
370
|
+
- Tailwind CSS v4 のユーティリティクラスを使用してスタイルを定義
|
|
371
|
+
- CSS変数(globals.css)でデザイントークンを管理
|
|
372
|
+
- shadcn/ui のコンポーネントを活用
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
// ユーティリティクラスの使用
|
|
376
|
+
<div className="flex items-center gap-4 rounded-lg bg-white p-6 shadow-md">
|
|
377
|
+
<h2 className="text-xl font-bold text-gray-900">Title</h2>
|
|
378
|
+
</div>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### cva によるバリアント管理
|
|
382
|
+
|
|
383
|
+
#### 基本的な使用方法
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
import { cva } from "class-variance-authority";
|
|
387
|
+
import { cn } from "@repo/ui/utils";
|
|
388
|
+
|
|
389
|
+
const buttonVariants = cva(
|
|
390
|
+
"inline-flex items-center justify-center rounded-md font-medium transition-colors",
|
|
391
|
+
{
|
|
392
|
+
variants: {
|
|
393
|
+
variant: {
|
|
394
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
395
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
396
|
+
outline: "border border-input bg-transparent hover:bg-accent",
|
|
397
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
398
|
+
},
|
|
399
|
+
size: {
|
|
400
|
+
sm: "h-8 px-3 text-sm",
|
|
401
|
+
md: "h-10 px-4 text-base",
|
|
402
|
+
lg: "h-12 px-6 text-lg",
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
defaultVariants: {
|
|
406
|
+
variant: "primary",
|
|
407
|
+
size: "md",
|
|
408
|
+
},
|
|
409
|
+
}
|
|
410
|
+
);
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### クラス名の結合
|
|
414
|
+
|
|
415
|
+
#### cn(className)ユーティリティの使用
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
import { cn } from "@repo/ui/utils";
|
|
419
|
+
|
|
420
|
+
export function Card({ className, children }: CardProps) {
|
|
421
|
+
return (
|
|
422
|
+
<div className={cn("border rounded-lg p-4", className)}>
|
|
423
|
+
{children}
|
|
424
|
+
</div>
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
#### 条件付きスタイル
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { cn } from "@repo/ui/utils";
|
|
433
|
+
|
|
434
|
+
export function Button({ isActive, className }: ButtonProps) {
|
|
435
|
+
return (
|
|
436
|
+
<button
|
|
437
|
+
className={cn(
|
|
438
|
+
"px-4 py-2 rounded-md",
|
|
439
|
+
isActive ? "bg-blue-500 text-white" : "bg-gray-200 text-gray-900",
|
|
440
|
+
className
|
|
441
|
+
)}
|
|
442
|
+
>
|
|
443
|
+
Click me
|
|
444
|
+
</button>
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### レスポンシブデザイン
|
|
450
|
+
|
|
451
|
+
#### ブレークポイント
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
<div className="text-sm p-2 md:text-base md:p-4 lg:text-lg lg:p-6">
|
|
455
|
+
レスポンシブコンテンツ
|
|
456
|
+
</div>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### カスタムブレークポイント
|
|
460
|
+
- sm: 640px
|
|
461
|
+
- md: 768px
|
|
462
|
+
- lg: 1024px
|
|
463
|
+
- xl: 1280px
|
|
464
|
+
- 2xl: 1440px
|
|
465
|
+
|
|
466
|
+
### ダークモード対応
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
<div className="bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100">
|
|
470
|
+
テーマ対応コンテンツ
|
|
471
|
+
</div>
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### ベストプラクティス
|
|
475
|
+
|
|
476
|
+
#### 1. デザイントークンの活用
|
|
477
|
+
- `globals.css` で定義されたCSS変数を使用
|
|
478
|
+
- shadcn/ui のカラートークンを活用(`text-primary`, `bg-muted` 等)
|
|
479
|
+
|
|
480
|
+
#### 2. shadcn/ui コンポーネントを優先
|
|
481
|
+
- 既存の shadcn/ui コンポーネントを優先的に使用
|
|
482
|
+
- カスタムが必要な場合のみ cva で独自バリアントを定義
|
|
483
|
+
|
|
484
|
+
#### 3. スタイルの一貫性
|
|
485
|
+
- プロジェクト全体で同じTailwindユーティリティパターンを使用
|
|
486
|
+
- カラーパレット、スペーシングの統一
|
|
487
|
+
|
|
488
|
+
## 関連ドキュメント
|
|
489
|
+
|
|
490
|
+
- `docs/einja/steering/development/coding-standards.md` - コーディング規約
|
|
491
|
+
- `docs/einja/steering/development/testing-strategy.md` - テスト戦略
|
|
492
|
+
- `docs/einja/steering/development/frontend-development.md` - フロントエンド開発ガイド
|
|
493
|
+
|
|
494
|
+
## 参考資料
|
|
495
|
+
|
|
496
|
+
- [React 公式ドキュメント](https://react.dev)
|
|
497
|
+
- [TypeScript 公式ドキュメント](https://www.typescriptlang.org)
|
|
498
|
+
- [Tailwind CSS ドキュメント](https://tailwindcss.com)
|
|
499
|
+
|
|
500
|
+
<!-- @einja:project-private:start id="component-design-project" -->
|
|
501
|
+
<!-- プロジェクト固有の情報を記入 -->
|
|
502
|
+
<!-- @einja:project-private:end -->
|
|
@@ -231,9 +231,58 @@ model NewFeature {
|
|
|
231
231
|
|
|
232
232
|
---
|
|
233
233
|
|
|
234
|
-
<!-- @einja:
|
|
235
|
-
##
|
|
234
|
+
<!-- @einja:project-private:start id="database-guidelines-project" -->
|
|
235
|
+
## プロジェクト固有: Prismaスキーマ編集ルール
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
### model名の命名規則
|
|
238
|
+
|
|
239
|
+
- モデル名は**アッパーキャメルケース**(例: `UserProfile`, `OrderItem`)
|
|
240
|
+
- `@@map()` でスネークケースのテーブル名を指定する
|
|
241
|
+
|
|
242
|
+
```prisma
|
|
243
|
+
model UserProfile {
|
|
244
|
+
// ...
|
|
245
|
+
@@map("user_profiles")
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### カラム名の命名規則
|
|
250
|
+
|
|
251
|
+
- カラム名は**キャメルケース**(例: `customerId`, `firstName`)
|
|
252
|
+
- `@map()` でスネークケースのDB名を指定する
|
|
253
|
+
|
|
254
|
+
```prisma
|
|
255
|
+
customerId String @map("customer_id")
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 必須・非必須の判定
|
|
259
|
+
|
|
260
|
+
- 指示されている、自明である、または他データソースによって確実に判定できる場合のみ設定する
|
|
261
|
+
- **推測で決定しない**。不明な場合は必ずユーザーに確認すること
|
|
262
|
+
|
|
263
|
+
### IDの採番
|
|
264
|
+
|
|
265
|
+
- `id` は **cuid** で自動採番を原則とする
|
|
266
|
+
|
|
267
|
+
```prisma
|
|
268
|
+
id String @id @default(cuid()) @map("id")
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### createdAt / updatedAt
|
|
272
|
+
|
|
273
|
+
- 原則としてすべてのテーブルに適用する
|
|
274
|
+
- `@db.Timestamptz(6)` を必ず明示する(PostgreSQL/Prisma公式推奨)
|
|
275
|
+
|
|
276
|
+
```prisma
|
|
277
|
+
createdAt DateTime @default(now()) @db.Timestamptz(6) @map("created_at")
|
|
278
|
+
updatedAt DateTime @updatedAt @db.Timestamptz(6) @map("updated_at")
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### 外部キーの削除ポリシー
|
|
282
|
+
|
|
283
|
+
- 外部キーを持つリレーションは、基本的に `onDelete: Cascade` の適用を検討する
|
|
284
|
+
|
|
285
|
+
```prisma
|
|
286
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
287
|
+
```
|
|
288
|
+
<!-- @einja:project-private:end -->
|
|
@@ -1760,11 +1760,6 @@ export function PostCreateForm() {
|
|
|
1760
1760
|
このガイドラインに従うことで、高速で保守性の高いモダンなWebアプリケーションを構築できます。
|
|
1761
1761
|
<!-- @einja:managed:end -->
|
|
1762
1762
|
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
<!-- @einja:
|
|
1766
|
-
## プロジェクト固有の設定
|
|
1767
|
-
|
|
1768
|
-
<!-- このセクションはプロジェクト固有の内容を追記する場所です -->
|
|
1769
|
-
<!-- einja syncで上書きされません -->
|
|
1770
|
-
<!-- @einja:seed:end -->
|
|
1763
|
+
<!-- @einja:project-private:start id="frontend-development-project" -->
|
|
1764
|
+
<!-- プロジェクト固有の情報を記入 -->
|
|
1765
|
+
<!-- @einja:project-private:end -->
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!-- @einja:managed -->
|
|
2
|
+
|
|
3
|
+
# Playwright MCP 動作確認ガイドライン
|
|
4
|
+
|
|
5
|
+
## 概要
|
|
6
|
+
|
|
7
|
+
Playwright MCPを使用した動作確認(スクリーンショット、ログ、スナップショット等)で生成される一時ファイルの管理ルールを定義します。
|
|
8
|
+
|
|
9
|
+
## 一時ファイル保存先
|
|
10
|
+
|
|
11
|
+
### 必須ルール
|
|
12
|
+
|
|
13
|
+
- **保存先**: すべての一時ファイルは `tmp/playwright-mcp/` 配下に保存すること
|
|
14
|
+
- **リポジトリルート直下や他ディレクトリへの一時ファイル保存は禁止**
|
|
15
|
+
- ディレクトリが存在しない場合は事前に作成すること:
|
|
16
|
+
```bash
|
|
17
|
+
mkdir -p tmp/playwright-mcp/
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### `browser_take_screenshot` の使用例
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
mcp__playwright__browser_take_screenshot({ fullPage: true, path: "tmp/playwright-mcp/dashboard-check.png" })
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**注意**: `path` パラメータには必ず `tmp/playwright-mcp/` プレフィックスを付けること。
|
|
27
|
+
|
|
28
|
+
### ファイル命名規約
|
|
29
|
+
|
|
30
|
+
- スクリーンショット: `tmp/playwright-mcp/{画面名}-{状態}.png`
|
|
31
|
+
- 例: `tmp/playwright-mcp/dashboard-initial.png`
|
|
32
|
+
- 例: `tmp/playwright-mcp/settings-after-update.png`
|
|
33
|
+
- コンソールログ: `tmp/playwright-mcp/console-{timestamp}.log`
|
|
34
|
+
- スナップショット: `tmp/playwright-mcp/{画面名}-snapshot.md`
|
|
35
|
+
|
|
36
|
+
### 例外
|
|
37
|
+
|
|
38
|
+
- **QAエビデンス用スクリーンショット**: `qa-tests/` 配下に保存(task-qaのルールに従う)
|
|
39
|
+
- QAエビデンスはGit管理対象のため、`tmp/` ではなく `qa-tests/` に配置する
|
|
40
|
+
|
|
41
|
+
## ブラウザリサイズ(必須)
|
|
42
|
+
|
|
43
|
+
Playwright MCPの操作を行う前に、必ずブラウザリサイズを実行すること:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
mcp__playwright__browser_resize({ width: 1280, height: 720 })
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**注意**: リサイズ未実施の場合、hookによって操作がブロックされます。
|
|
50
|
+
|
|
51
|
+
## Git管理
|
|
52
|
+
|
|
53
|
+
- `tmp/` ディレクトリは `.gitignore` で除外済み
|
|
54
|
+
- 一時ファイルはGitにコミットされない
|
|
55
|
+
- QAエビデンスが必要な場合は `qa-tests/` を使用すること
|
|
56
|
+
|
|
57
|
+
<!-- @einja:project-private:start id="playwright-guidelines-project" -->
|
|
58
|
+
<!-- プロジェクト固有の情報を記入 -->
|
|
59
|
+
<!-- @einja:project-private:end -->
|
|
@@ -371,11 +371,6 @@ task-reviewerエージェントは以下の4観点を**Taskツールで並列に
|
|
|
371
371
|
- **トレードオフの考慮**: パフォーマンス、可読性、保守性のバランスを考慮
|
|
372
372
|
<!-- @einja:managed:end -->
|
|
373
373
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
<!-- @einja:
|
|
377
|
-
## プロジェクト固有の設定
|
|
378
|
-
|
|
379
|
-
<!-- このセクションはプロジェクト固有の内容を追記する場所です -->
|
|
380
|
-
<!-- einja syncで上書きされません -->
|
|
381
|
-
<!-- @einja:seed:end -->
|
|
374
|
+
<!-- @einja:project-private:start id="review-guidelines-project" -->
|
|
375
|
+
<!-- プロジェクト固有の情報を記入 -->
|
|
376
|
+
<!-- @einja:project-private:end -->
|
|
@@ -894,11 +894,6 @@ describe('UserUseCase', () => {
|
|
|
894
894
|
すべてのテストは、このガイドラインに従って実装してください。
|
|
895
895
|
<!-- @einja:managed:end -->
|
|
896
896
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
<!-- @einja:
|
|
900
|
-
## プロジェクト固有の設定
|
|
901
|
-
|
|
902
|
-
<!-- このセクションはプロジェクト固有の内容を追記する場所です -->
|
|
903
|
-
<!-- einja syncで上書きされません -->
|
|
904
|
-
<!-- @einja:seed:end -->
|
|
897
|
+
<!-- @einja:project-private:start id="testing-strategy-project" -->
|
|
898
|
+
<!-- プロジェクト固有の情報を記入 -->
|
|
899
|
+
<!-- @einja:project-private:end -->
|