@hienlh/ppm 0.1.0
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/.claude/agent-memory/tester/MEMORY.md +3 -0
- package/.claude/agent-memory/tester/project-ppm-test-conventions.md +32 -0
- package/.env.example +1 -0
- package/.github/workflows/release.yml +46 -0
- package/README.md +349 -0
- package/bun.lock +1217 -0
- package/components.json +21 -0
- package/docs/code-standards.md +574 -0
- package/docs/codebase-summary.md +294 -0
- package/docs/deployment-guide.md +631 -0
- package/docs/design-guidelines.md +661 -0
- package/docs/project-overview-pdr.md +142 -0
- package/docs/project-roadmap.md +400 -0
- package/docs/system-architecture.md +459 -0
- package/package.json +68 -0
- package/plans/260314-2009-ppm-implementation/phase-01-project-skeleton.md +81 -0
- package/plans/260314-2009-ppm-implementation/phase-02-backend-core.md +148 -0
- package/plans/260314-2009-ppm-implementation/phase-03-frontend-shell.md +256 -0
- package/plans/260314-2009-ppm-implementation/phase-04-file-explorer-editor.md +120 -0
- package/plans/260314-2009-ppm-implementation/phase-05-web-terminal.md +174 -0
- package/plans/260314-2009-ppm-implementation/phase-06-git-integration.md +244 -0
- package/plans/260314-2009-ppm-implementation/phase-07-ai-chat.md +242 -0
- package/plans/260314-2009-ppm-implementation/phase-08-cli-commands.md +143 -0
- package/plans/260314-2009-ppm-implementation/phase-09-pwa-build-deploy.md +209 -0
- package/plans/260314-2009-ppm-implementation/phase-10-testing.md +311 -0
- package/plans/260314-2009-ppm-implementation/plan.md +202 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-01-backend-project-router.md +145 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-02-frontend-api-migration.md +107 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-03-per-project-tabs.md +100 -0
- package/plans/260315-0356-project-scoped-api-refactor/phase-04-websocket-migration.md +66 -0
- package/plans/260315-0356-project-scoped-api-refactor/plan.md +87 -0
- package/plans/reports/brainstorm-260314-1938-final-techstack.md +342 -0
- package/plans/reports/docs-manager-260315-1314-documentation-creation.md +386 -0
- package/plans/reports/fullstack-developer-260314-2252-phase-02-backend-core.md +57 -0
- package/plans/reports/fullstack-developer-260314-2253-phase-03-frontend-shell.md +70 -0
- package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-api-terminal-ws.md +49 -0
- package/plans/reports/fullstack-developer-260314-2300-phase-04-05-file-explorer-editor-terminal.md +52 -0
- package/plans/reports/fullstack-developer-260314-2307-ai-chat-phase7.md +58 -0
- package/plans/reports/fullstack-developer-260314-2307-phase-06-git-integration.md +33 -0
- package/plans/reports/research-260314-1911-ppm-tech-stack.md +318 -0
- package/plans/reports/research-260314-1930-claude-code-integration.md +293 -0
- package/plans/reports/researcher-260314-2232-node-pty-bun-crash-analysis.md +305 -0
- package/plans/reports/researcher-260314-2232-ui-style.md +942 -0
- package/plans/reports/researcher-260315-0300-opcode-claude-interaction.md +745 -0
- package/plans/reports/researcher-260315-0303-opcode-deep-analysis.md +742 -0
- package/plans/reports/researcher-260315-0305-claude-agent-sdk-github-research.md +423 -0
- package/plans/reports/tester-260314-2053-initial-test-suite.md +81 -0
- package/ppm.example.yaml +14 -0
- package/repomix-output.xml +23745 -0
- package/scripts/build.ts +13 -0
- package/src/cli/commands/chat-cmd.ts +259 -0
- package/src/cli/commands/config-cmd.ts +121 -0
- package/src/cli/commands/git-cmd.ts +315 -0
- package/src/cli/commands/init.ts +57 -0
- package/src/cli/commands/open.ts +19 -0
- package/src/cli/commands/projects.ts +100 -0
- package/src/cli/commands/start.ts +3 -0
- package/src/cli/commands/stop.ts +33 -0
- package/src/cli/utils/project-resolver.ts +27 -0
- package/src/index.ts +59 -0
- package/src/providers/claude-agent-sdk.ts +499 -0
- package/src/providers/claude-binary-finder.ts +256 -0
- package/src/providers/claude-code-cli.ts +413 -0
- package/src/providers/claude-process-registry.ts +106 -0
- package/src/providers/mock-provider.ts +171 -0
- package/src/providers/provider.interface.ts +10 -0
- package/src/providers/registry.ts +45 -0
- package/src/server/helpers/resolve-project.ts +22 -0
- package/src/server/index.ts +181 -0
- package/src/server/middleware/auth.ts +30 -0
- package/src/server/routes/chat.ts +153 -0
- package/src/server/routes/files.ts +168 -0
- package/src/server/routes/git.ts +261 -0
- package/src/server/routes/project-scoped.ts +27 -0
- package/src/server/routes/projects.ts +57 -0
- package/src/server/routes/static.ts +26 -0
- package/src/server/ws/chat.ts +130 -0
- package/src/server/ws/terminal.ts +89 -0
- package/src/services/chat.service.ts +110 -0
- package/src/services/claude-usage.service.ts +113 -0
- package/src/services/config.service.ts +90 -0
- package/src/services/file.service.ts +261 -0
- package/src/services/git-dirs.service.ts +112 -0
- package/src/services/git.service.ts +372 -0
- package/src/services/project.service.ts +107 -0
- package/src/services/slash-items.service.ts +184 -0
- package/src/services/terminal.service.ts +212 -0
- package/src/types/api.ts +37 -0
- package/src/types/chat.ts +92 -0
- package/src/types/config.ts +41 -0
- package/src/types/git.ts +50 -0
- package/src/types/project.ts +18 -0
- package/src/types/terminal.ts +20 -0
- package/src/web/app.tsx +168 -0
- package/src/web/components/auth/login-screen.tsx +88 -0
- package/src/web/components/chat/attachment-chips.tsx +55 -0
- package/src/web/components/chat/chat-placeholder.tsx +10 -0
- package/src/web/components/chat/chat-tab.tsx +301 -0
- package/src/web/components/chat/file-picker.tsx +126 -0
- package/src/web/components/chat/message-input.tsx +420 -0
- package/src/web/components/chat/message-list.tsx +838 -0
- package/src/web/components/chat/session-picker.tsx +139 -0
- package/src/web/components/chat/slash-command-picker.tsx +135 -0
- package/src/web/components/chat/usage-badge.tsx +186 -0
- package/src/web/components/editor/code-editor.tsx +329 -0
- package/src/web/components/editor/diff-viewer.tsx +276 -0
- package/src/web/components/editor/editor-placeholder.tsx +10 -0
- package/src/web/components/explorer/file-actions.tsx +191 -0
- package/src/web/components/explorer/file-tree.tsx +298 -0
- package/src/web/components/git/git-graph.tsx +727 -0
- package/src/web/components/git/git-placeholder.tsx +55 -0
- package/src/web/components/git/git-status-panel.tsx +850 -0
- package/src/web/components/layout/mobile-drawer.tsx +137 -0
- package/src/web/components/layout/mobile-nav.tsx +103 -0
- package/src/web/components/layout/sidebar.tsx +90 -0
- package/src/web/components/layout/tab-bar.tsx +152 -0
- package/src/web/components/layout/tab-content.tsx +85 -0
- package/src/web/components/projects/dir-suggest.tsx +152 -0
- package/src/web/components/projects/project-list.tsx +187 -0
- package/src/web/components/settings/settings-tab.tsx +57 -0
- package/src/web/components/terminal/terminal-placeholder.tsx +10 -0
- package/src/web/components/terminal/terminal-tab.tsx +133 -0
- package/src/web/components/ui/button.tsx +64 -0
- package/src/web/components/ui/context-menu.tsx +250 -0
- package/src/web/components/ui/dialog.tsx +156 -0
- package/src/web/components/ui/dropdown-menu.tsx +257 -0
- package/src/web/components/ui/input.tsx +21 -0
- package/src/web/components/ui/scroll-area.tsx +56 -0
- package/src/web/components/ui/separator.tsx +26 -0
- package/src/web/components/ui/sonner.tsx +40 -0
- package/src/web/components/ui/tabs.tsx +91 -0
- package/src/web/components/ui/tooltip.tsx +57 -0
- package/src/web/hooks/use-chat.ts +420 -0
- package/src/web/hooks/use-terminal.ts +182 -0
- package/src/web/hooks/use-url-sync.ts +66 -0
- package/src/web/hooks/use-websocket.ts +48 -0
- package/src/web/index.html +16 -0
- package/src/web/lib/api-client.ts +90 -0
- package/src/web/lib/file-support.ts +68 -0
- package/src/web/lib/utils.ts +6 -0
- package/src/web/lib/ws-client.ts +100 -0
- package/src/web/main.tsx +10 -0
- package/src/web/public/icon-192.svg +5 -0
- package/src/web/public/icon-512.svg +5 -0
- package/src/web/stores/file-store.ts +81 -0
- package/src/web/stores/project-store.ts +50 -0
- package/src/web/stores/settings-store.ts +65 -0
- package/src/web/stores/tab-store.ts +187 -0
- package/src/web/styles/globals.css +227 -0
- package/src/web/vite-env.d.ts +1 -0
- package/tests/integration/api/chat-routes.test.ts +95 -0
- package/tests/integration/claude-agent-sdk-integration.test.ts +228 -0
- package/tests/integration/ws/chat-websocket.test.ts +312 -0
- package/tests/test-setup.ts +5 -0
- package/tests/unit/providers/claude-agent-sdk.test.ts +339 -0
- package/tests/unit/providers/mock-provider.test.ts +143 -0
- package/tests/unit/services/chat-service.test.ts +100 -0
- package/tsconfig.json +32 -0
- package/vite.config.ts +62 -0
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
# PPM Design Guidelines
|
|
2
|
+
|
|
3
|
+
## Design Philosophy
|
|
4
|
+
|
|
5
|
+
**PPM** prioritizes **clarity, efficiency, and accessibility** over decoration. The UI should feel lightweight, responsive, and get out of the way of actual development work.
|
|
6
|
+
|
|
7
|
+
**Core Principles:**
|
|
8
|
+
1. **Mobile-first** — Design for small screens, scale up
|
|
9
|
+
2. **Dark-mode default** — Reduce eye strain during long coding sessions
|
|
10
|
+
3. **Minimal chrome** — Maximize editor/terminal space
|
|
11
|
+
4. **Keyboard-friendly** — Power users prefer shortcuts
|
|
12
|
+
5. **Accessible** — WCAG 2.1 AA compliance
|
|
13
|
+
6. **Consistent** — Reuse patterns across features
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## UI Framework Stack
|
|
18
|
+
|
|
19
|
+
### Tailwind CSS 4.2
|
|
20
|
+
- Utility-first CSS framework
|
|
21
|
+
- Dark mode support (class-based: `dark:` prefix)
|
|
22
|
+
- Responsive breakpoints (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`)
|
|
23
|
+
- Custom configuration in `tailwind.config.ts`
|
|
24
|
+
|
|
25
|
+
### Radix UI 1.4.3
|
|
26
|
+
- Unstyled, accessible components
|
|
27
|
+
- Provides accessibility (ARIA, keyboard navigation)
|
|
28
|
+
- Examples: Dialog, Dropdown, Tooltip, Tabs
|
|
29
|
+
- No CSS imports; styled with Tailwind
|
|
30
|
+
|
|
31
|
+
### shadcn/ui (New York Style)
|
|
32
|
+
- Pre-built Radix components with Tailwind styling
|
|
33
|
+
- Copy-paste component library (not npm-installed)
|
|
34
|
+
- Located in `src/web/components/ui/`
|
|
35
|
+
- Customizable and maintainable
|
|
36
|
+
|
|
37
|
+
### Lucide Icons
|
|
38
|
+
- Clean, consistent icon set
|
|
39
|
+
- 600+ icons available
|
|
40
|
+
- Usage: `import { FileIcon, FolderIcon } from "lucide-react"`
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Color Scheme
|
|
45
|
+
|
|
46
|
+
### Light Mode
|
|
47
|
+
|
|
48
|
+
| Purpose | Color | Tailwind | Usage |
|
|
49
|
+
|---------|-------|----------|-------|
|
|
50
|
+
| Background | #FFFFFF | `bg-white` | Page background |
|
|
51
|
+
| Foreground | #000000 | `text-black` | Primary text |
|
|
52
|
+
| Sidebar | #F3F4F6 | `bg-gray-100` | Navigation panel |
|
|
53
|
+
| Border | #E5E7EB | `border-gray-200` | Dividers, edges |
|
|
54
|
+
| Accent | #3B82F6 | `bg-blue-500` | Links, active states |
|
|
55
|
+
| Hover | #DBEAFE | `hover:bg-blue-100` | Interactive states |
|
|
56
|
+
| Danger | #EF4444 | `bg-red-500` | Destructive actions |
|
|
57
|
+
| Success | #10B981 | `bg-green-500` | Positive feedback |
|
|
58
|
+
|
|
59
|
+
### Dark Mode
|
|
60
|
+
|
|
61
|
+
| Purpose | Color | Tailwind | Usage |
|
|
62
|
+
|---------|-------|----------|-------|
|
|
63
|
+
| Background | #0F172A | `dark:bg-slate-950` | Page background |
|
|
64
|
+
| Foreground | #F1F5F9 | `dark:text-slate-100` | Primary text |
|
|
65
|
+
| Sidebar | #1E293B | `dark:bg-slate-800` | Navigation panel |
|
|
66
|
+
| Border | #334155 | `dark:border-slate-700` | Dividers, edges |
|
|
67
|
+
| Accent | #3B82F6 | `dark:bg-blue-500` | Links, active states |
|
|
68
|
+
| Hover | #1E3A8A | `dark:hover:bg-blue-900` | Interactive states |
|
|
69
|
+
| Danger | #EF4444 | `dark:bg-red-600` | Destructive actions |
|
|
70
|
+
| Success | #10B981 | `dark:bg-green-600` | Positive feedback |
|
|
71
|
+
|
|
72
|
+
### Implementation
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
// Auto-detected based on system preference
|
|
76
|
+
// Or manually controlled via SettingsStore
|
|
77
|
+
|
|
78
|
+
// Dark mode uses: <html class="dark">
|
|
79
|
+
// Tailwind applies dark: prefix styles
|
|
80
|
+
|
|
81
|
+
// Example component
|
|
82
|
+
<button className="bg-white dark:bg-slate-800 text-black dark:text-white">
|
|
83
|
+
Click me
|
|
84
|
+
</button>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Typography
|
|
90
|
+
|
|
91
|
+
### Font Stack
|
|
92
|
+
|
|
93
|
+
```css
|
|
94
|
+
/* tailwind.config.ts */
|
|
95
|
+
theme: {
|
|
96
|
+
fontFamily: {
|
|
97
|
+
sans: ['Inter', 'system-ui', 'sans-serif'],
|
|
98
|
+
mono: ['JetBrains Mono', 'Monaco', 'Courier New', 'monospace'],
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Type Scale
|
|
104
|
+
|
|
105
|
+
| Usage | Size | Line Height | Weight |
|
|
106
|
+
|-------|------|-------------|--------|
|
|
107
|
+
| H1 (Title) | 32px | 1.2 | 700 (bold) |
|
|
108
|
+
| H2 (Heading) | 24px | 1.3 | 600 (semibold) |
|
|
109
|
+
| H3 (Subheading) | 20px | 1.4 | 600 (semibold) |
|
|
110
|
+
| Body | 14px | 1.5 | 400 (regular) |
|
|
111
|
+
| Small | 12px | 1.4 | 400 (regular) |
|
|
112
|
+
| Code | 13px | 1.6 | 400 (monospace) |
|
|
113
|
+
|
|
114
|
+
### Example
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
// Heading
|
|
118
|
+
<h1 className="text-2xl font-bold">PPM</h1>
|
|
119
|
+
|
|
120
|
+
// Body text
|
|
121
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">
|
|
122
|
+
Descriptive text
|
|
123
|
+
</p>
|
|
124
|
+
|
|
125
|
+
// Code/terminal text
|
|
126
|
+
<code className="font-mono text-xs bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded">
|
|
127
|
+
npm install
|
|
128
|
+
</code>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Component Patterns
|
|
134
|
+
|
|
135
|
+
### Button Component
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
// Base button from shadcn/ui
|
|
139
|
+
import { Button } from "@/components/ui/button";
|
|
140
|
+
|
|
141
|
+
// Variants
|
|
142
|
+
<Button>Primary</Button>
|
|
143
|
+
<Button variant="outline">Outline</Button>
|
|
144
|
+
<Button variant="ghost">Ghost</Button>
|
|
145
|
+
<Button variant="destructive">Delete</Button>
|
|
146
|
+
<Button disabled>Disabled</Button>
|
|
147
|
+
|
|
148
|
+
// Sizes
|
|
149
|
+
<Button size="sm">Small</Button>
|
|
150
|
+
<Button size="default">Default</Button>
|
|
151
|
+
<Button size="lg">Large</Button>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Input Component
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { Input } from "@/components/ui/input";
|
|
158
|
+
|
|
159
|
+
<Input
|
|
160
|
+
type="text"
|
|
161
|
+
placeholder="Enter search..."
|
|
162
|
+
className="h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
163
|
+
/>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Dialog Component
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
|
170
|
+
|
|
171
|
+
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
|
172
|
+
<DialogContent>
|
|
173
|
+
<DialogHeader>
|
|
174
|
+
<DialogTitle>Confirm Action</DialogTitle>
|
|
175
|
+
</DialogHeader>
|
|
176
|
+
<p>Are you sure?</p>
|
|
177
|
+
</DialogContent>
|
|
178
|
+
</Dialog>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Dropdown Menu
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import {
|
|
185
|
+
DropdownMenu,
|
|
186
|
+
DropdownMenuContent,
|
|
187
|
+
DropdownMenuItem,
|
|
188
|
+
DropdownMenuTrigger,
|
|
189
|
+
} from "@/components/ui/dropdown-menu";
|
|
190
|
+
|
|
191
|
+
<DropdownMenu>
|
|
192
|
+
<DropdownMenuTrigger asChild>
|
|
193
|
+
<Button variant="ghost" size="sm">•••</Button>
|
|
194
|
+
</DropdownMenuTrigger>
|
|
195
|
+
<DropdownMenuContent>
|
|
196
|
+
<DropdownMenuItem>Edit</DropdownMenuItem>
|
|
197
|
+
<DropdownMenuItem>Delete</DropdownMenuItem>
|
|
198
|
+
</DropdownMenuContent>
|
|
199
|
+
</DropdownMenu>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Layout Structure
|
|
205
|
+
|
|
206
|
+
### Desktop Layout
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
┌─────────────────────────────────────────────────────────┐
|
|
210
|
+
│ Sidebar (300px) │ MainArea │
|
|
211
|
+
├──────────────────┼─────────────────────────────────────┤
|
|
212
|
+
│ Project Selector │ ┌───────────────────────────────────┐│
|
|
213
|
+
├──────────────────┤ │ TabBar (Chat | Editor | Git | … )││
|
|
214
|
+
│ File Explorer │ ├───────────────────────────────────┤│
|
|
215
|
+
│ │ │ Tab Content (varies) ││
|
|
216
|
+
│ • src/ │ │ CodeEditor, ChatTab, etc. ││
|
|
217
|
+
│ - main.ts │ │ ││
|
|
218
|
+
│ - utils.ts │ │ ││
|
|
219
|
+
│ │ │ ││
|
|
220
|
+
│ • dist/ │ │ (Fills remaining space) ││
|
|
221
|
+
│ │ │ ││
|
|
222
|
+
│ │ │ ││
|
|
223
|
+
│ │ └───────────────────────────────────┘│
|
|
224
|
+
└──────────────────┴─────────────────────────────────────┘
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Sidebar:** 300px fixed, scrollable, dark background
|
|
228
|
+
**MainArea:** Flex 1, contains TabBar + content
|
|
229
|
+
**TabBar:** Horizontal tabs (chat, editor, git, terminal, settings)
|
|
230
|
+
**Content:** Flex, fills remaining space, scrollable if needed
|
|
231
|
+
|
|
232
|
+
### Mobile Layout
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
┌─────────────────────────────────────┐
|
|
236
|
+
│ ☰ | Project Selector | ⚙️ │
|
|
237
|
+
├─────────────────────────────────────┤
|
|
238
|
+
│ MainArea (full width) │
|
|
239
|
+
│ │
|
|
240
|
+
│ ChatTab / EditorTab / etc. │
|
|
241
|
+
│ │
|
|
242
|
+
│ (Sidebar hidden, accessible via ☰) │
|
|
243
|
+
├─────────────────────────────────────┤
|
|
244
|
+
│ TabBar (bottom, horizontal scroll) │
|
|
245
|
+
│ [Chat] [Editor] [Git] [Terminal] │
|
|
246
|
+
└─────────────────────────────────────┘
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Header:** Project selector + hamburger menu
|
|
250
|
+
**Content:** Full-width tab content
|
|
251
|
+
**TabBar:** Bottom navigation (mobile-friendly)
|
|
252
|
+
**Sidebar:** Slide-in drawer (MobileDrawer component)
|
|
253
|
+
|
|
254
|
+
### Responsive Breakpoints
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// tailwind.config.ts
|
|
258
|
+
screens: {
|
|
259
|
+
sm: '640px', // Mobile
|
|
260
|
+
md: '768px', // Tablet
|
|
261
|
+
lg: '1024px', // Desktop
|
|
262
|
+
xl: '1280px', // Wide desktop
|
|
263
|
+
'2xl': '1536px' // Ultra-wide
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Rules:**
|
|
268
|
+
- `sm:` and below — Mobile optimizations
|
|
269
|
+
- `md:` and above — Show sidebar
|
|
270
|
+
- `lg:` and above — Full-width optimizations
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Component Library Usage
|
|
275
|
+
|
|
276
|
+
### File Tree Component
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
// src/web/components/explorer/file-tree.tsx
|
|
280
|
+
// Shows directory structure with expand/collapse
|
|
281
|
+
|
|
282
|
+
<FileTree
|
|
283
|
+
root={project.root}
|
|
284
|
+
onSelect={(file) => openFile(file)}
|
|
285
|
+
onContextMenu={(file) => showMenu(file)}
|
|
286
|
+
/>
|
|
287
|
+
|
|
288
|
+
// Features:
|
|
289
|
+
// - Lazy load directories (expand on click)
|
|
290
|
+
// - File icons based on extension
|
|
291
|
+
// - Highlight current file
|
|
292
|
+
// - Right-click context menu (create, delete, etc.)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Code Editor
|
|
296
|
+
|
|
297
|
+
```tsx
|
|
298
|
+
// src/web/components/editor/code-editor.tsx
|
|
299
|
+
// CodeMirror 6 integration with syntax highlighting
|
|
300
|
+
|
|
301
|
+
<CodeEditor
|
|
302
|
+
language="javascript"
|
|
303
|
+
value={fileContent}
|
|
304
|
+
onChange={setFileContent}
|
|
305
|
+
theme="dark"
|
|
306
|
+
readOnly={false}
|
|
307
|
+
/>
|
|
308
|
+
|
|
309
|
+
// Features:
|
|
310
|
+
// - 50+ language support
|
|
311
|
+
// - Real-time syntax highlighting
|
|
312
|
+
// - Line numbers, code folding
|
|
313
|
+
// - Find/replace (Ctrl+H)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Terminal Component
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
// src/web/components/terminal/terminal-tab.tsx
|
|
320
|
+
// xterm.js integration
|
|
321
|
+
|
|
322
|
+
<TerminalTab projectName={project.name} />
|
|
323
|
+
|
|
324
|
+
// Features:
|
|
325
|
+
// - Full terminal emulation (bash/zsh)
|
|
326
|
+
// - 256 color support
|
|
327
|
+
// - Mouse support (click, scroll)
|
|
328
|
+
// - Resize handling
|
|
329
|
+
// - Copy/paste from clipboard
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Chat Component
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
// src/web/components/chat/chat-tab.tsx
|
|
336
|
+
// Message list + input with file attachments
|
|
337
|
+
|
|
338
|
+
<ChatTab sessionId={sessionId} />
|
|
339
|
+
|
|
340
|
+
// Features:
|
|
341
|
+
// - Streaming message display
|
|
342
|
+
// - Tool use cards (file_read, git commands)
|
|
343
|
+
// - File attachment previews
|
|
344
|
+
// - Slash command autocomplete
|
|
345
|
+
// - Session switcher
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Git Status Panel
|
|
349
|
+
|
|
350
|
+
```tsx
|
|
351
|
+
// src/web/components/git/git-status-panel.tsx
|
|
352
|
+
// Git status with staging UI
|
|
353
|
+
|
|
354
|
+
<GitStatusPanel projectName={project.name} />
|
|
355
|
+
|
|
356
|
+
// Features:
|
|
357
|
+
// - Staged/unstaged/untracked file lists
|
|
358
|
+
// - Stage/unstage buttons
|
|
359
|
+
// - Commit message input
|
|
360
|
+
// - Commit graph (Mermaid)
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Dark Mode Implementation
|
|
366
|
+
|
|
367
|
+
### Automatic Detection
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
// src/web/app.tsx
|
|
371
|
+
// Detect system preference
|
|
372
|
+
|
|
373
|
+
useEffect(() => {
|
|
374
|
+
const preference = window.matchMedia('(prefers-color-scheme: dark)');
|
|
375
|
+
const isDark = preference.matches;
|
|
376
|
+
setTheme(isDark ? 'dark' : 'light');
|
|
377
|
+
}, []);
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Manual Override
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
// Settings tab allows user to choose:
|
|
384
|
+
// - System (follow OS preference)
|
|
385
|
+
// - Dark (always dark)
|
|
386
|
+
// - Light (always light)
|
|
387
|
+
|
|
388
|
+
// Implementation via next-themes
|
|
389
|
+
<ThemeProvider attribute="class" defaultTheme="system">
|
|
390
|
+
<App />
|
|
391
|
+
</ThemeProvider>
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### CSS in Dark Mode
|
|
395
|
+
|
|
396
|
+
```tsx
|
|
397
|
+
// Tailwind dark: prefix
|
|
398
|
+
<div className="bg-white dark:bg-slate-950 text-black dark:text-white">
|
|
399
|
+
Content adapts to theme
|
|
400
|
+
</div>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## Responsive Design
|
|
406
|
+
|
|
407
|
+
### Mobile-First CSS
|
|
408
|
+
|
|
409
|
+
Start with mobile styles, add complexity for larger screens:
|
|
410
|
+
|
|
411
|
+
```css
|
|
412
|
+
/* Mobile-first */
|
|
413
|
+
.sidebar {
|
|
414
|
+
display: none; /* Hidden on mobile */
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* Tablet and up */
|
|
418
|
+
@media (min-width: 768px) {
|
|
419
|
+
.sidebar {
|
|
420
|
+
display: block;
|
|
421
|
+
width: 300px;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Or in Tailwind:**
|
|
427
|
+
```tsx
|
|
428
|
+
<div className="hidden md:block w-64">
|
|
429
|
+
Sidebar (hidden on mobile, shown on md+)
|
|
430
|
+
</div>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Touch-Friendly Sizes
|
|
434
|
+
|
|
435
|
+
- **Button height:** 44px minimum (iOS guideline)
|
|
436
|
+
- **Touch target:** 44×44px or larger
|
|
437
|
+
- **Spacing:** 16px minimum between interactive elements
|
|
438
|
+
|
|
439
|
+
```tsx
|
|
440
|
+
// Good: Touch-friendly
|
|
441
|
+
<button className="px-4 py-3 rounded-lg">Click</button>
|
|
442
|
+
|
|
443
|
+
// Avoid: Too small
|
|
444
|
+
<button className="px-2 py-1">Click</button>
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Viewport Configuration
|
|
448
|
+
|
|
449
|
+
```html
|
|
450
|
+
<!-- public/index.html -->
|
|
451
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## PWA Considerations
|
|
457
|
+
|
|
458
|
+
### Web App Manifest
|
|
459
|
+
|
|
460
|
+
```json
|
|
461
|
+
{
|
|
462
|
+
"name": "Personal Project Manager",
|
|
463
|
+
"short_name": "PPM",
|
|
464
|
+
"description": "Mobile-first web IDE for managing code projects",
|
|
465
|
+
"start_url": "/",
|
|
466
|
+
"scope": "/",
|
|
467
|
+
"display": "standalone",
|
|
468
|
+
"theme_color": "#0F172A",
|
|
469
|
+
"background_color": "#FFFFFF",
|
|
470
|
+
"icons": [
|
|
471
|
+
{
|
|
472
|
+
"src": "/icons/icon-192.png",
|
|
473
|
+
"sizes": "192x192",
|
|
474
|
+
"type": "image/png",
|
|
475
|
+
"purpose": "any"
|
|
476
|
+
}
|
|
477
|
+
]
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Service Worker
|
|
482
|
+
|
|
483
|
+
- Cache static assets (CSS, JS, images)
|
|
484
|
+
- Offline fallback (HTML, basic UI)
|
|
485
|
+
- Background sync (planned for v3)
|
|
486
|
+
|
|
487
|
+
### Installation Prompt
|
|
488
|
+
|
|
489
|
+
- Browser shows "Add to Home Screen" on first visit
|
|
490
|
+
- Users can install as standalone app
|
|
491
|
+
- App opens fullscreen without browser chrome
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## Animation & Micro-interactions
|
|
496
|
+
|
|
497
|
+
### Smooth Transitions
|
|
498
|
+
|
|
499
|
+
```css
|
|
500
|
+
/* Fade in content */
|
|
501
|
+
.fade-in {
|
|
502
|
+
animation: fadeIn 0.3s ease-in;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
@keyframes fadeIn {
|
|
506
|
+
from { opacity: 0; }
|
|
507
|
+
to { opacity: 1; }
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
### Button Hover States
|
|
512
|
+
|
|
513
|
+
```tsx
|
|
514
|
+
<button className="bg-blue-500 hover:bg-blue-600 active:bg-blue-700 transition-colors">
|
|
515
|
+
Click me
|
|
516
|
+
</button>
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### Loading Spinner
|
|
520
|
+
|
|
521
|
+
```tsx
|
|
522
|
+
<Spinner className="animate-spin w-5 h-5" />
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### Toast Notifications
|
|
526
|
+
|
|
527
|
+
```tsx
|
|
528
|
+
// sonner library for notifications
|
|
529
|
+
import { toast } from "sonner";
|
|
530
|
+
|
|
531
|
+
toast.success("File saved!");
|
|
532
|
+
toast.error("Failed to commit");
|
|
533
|
+
toast.loading("Pushing...");
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## Accessibility
|
|
539
|
+
|
|
540
|
+
### Keyboard Navigation
|
|
541
|
+
|
|
542
|
+
- **Tab order:** Logical flow (left-to-right, top-to-bottom)
|
|
543
|
+
- **Focus visible:** Clear focus indicator on interactive elements
|
|
544
|
+
- **Keyboard shortcuts:** Alt+S (save), Ctrl+K (command palette), etc.
|
|
545
|
+
|
|
546
|
+
```tsx
|
|
547
|
+
// Good: Focus visible
|
|
548
|
+
<button className="focus-visible:ring-2 focus-visible:ring-blue-500">
|
|
549
|
+
Click me
|
|
550
|
+
</button>
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Color Contrast
|
|
554
|
+
|
|
555
|
+
- **WCAG AA:** 4.5:1 for normal text, 3:1 for large text
|
|
556
|
+
- **Avoid:** Color-only indicators (use icons + text)
|
|
557
|
+
|
|
558
|
+
```tsx
|
|
559
|
+
// Good: Icon + text + color
|
|
560
|
+
<span className="text-red-600">
|
|
561
|
+
<ErrorIcon className="inline" /> Error occurred
|
|
562
|
+
</span>
|
|
563
|
+
|
|
564
|
+
// Avoid: Color only
|
|
565
|
+
<span className="text-red-600">Error</span>
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### ARIA Labels
|
|
569
|
+
|
|
570
|
+
```tsx
|
|
571
|
+
// Good: Descriptive labels
|
|
572
|
+
<button aria-label="Delete file">
|
|
573
|
+
<TrashIcon />
|
|
574
|
+
</button>
|
|
575
|
+
|
|
576
|
+
<input
|
|
577
|
+
type="text"
|
|
578
|
+
aria-label="Search projects"
|
|
579
|
+
placeholder="Search..."
|
|
580
|
+
/>
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Semantic HTML
|
|
584
|
+
|
|
585
|
+
```tsx
|
|
586
|
+
// Good: Semantic structure
|
|
587
|
+
<nav>Navigation here</nav>
|
|
588
|
+
<main>Main content</main>
|
|
589
|
+
<aside>Sidebar</aside>
|
|
590
|
+
<footer>Footer</footer>
|
|
591
|
+
|
|
592
|
+
// Avoid: Generic divs
|
|
593
|
+
<div>Navigation here</div>
|
|
594
|
+
<div>Main content</div>
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## Visual Hierarchy
|
|
600
|
+
|
|
601
|
+
### Size & Weight
|
|
602
|
+
|
|
603
|
+
Larger, bolder elements draw attention first:
|
|
604
|
+
|
|
605
|
+
```tsx
|
|
606
|
+
// Page title (largest, boldest)
|
|
607
|
+
<h1 className="text-3xl font-bold">Project Name</h1>
|
|
608
|
+
|
|
609
|
+
// Section heading (medium)
|
|
610
|
+
<h2 className="text-xl font-semibold">Files</h2>
|
|
611
|
+
|
|
612
|
+
// Regular text (small, normal weight)
|
|
613
|
+
<p className="text-sm font-normal">3 files</p>
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### Spacing & Whitespace
|
|
617
|
+
|
|
618
|
+
- **Compact:** 8px gutters between elements
|
|
619
|
+
- **Normal:** 16px padding inside containers
|
|
620
|
+
- **Generous:** 24px+ between major sections
|
|
621
|
+
|
|
622
|
+
```tsx
|
|
623
|
+
// Compact list
|
|
624
|
+
<ul className="space-y-1">
|
|
625
|
+
<li>Item 1</li>
|
|
626
|
+
<li>Item 2</li>
|
|
627
|
+
</ul>
|
|
628
|
+
|
|
629
|
+
// Generous spacing
|
|
630
|
+
<section className="mb-8">
|
|
631
|
+
<h2 className="mb-4">Title</h2>
|
|
632
|
+
<p className="mb-4">Paragraph 1</p>
|
|
633
|
+
<p>Paragraph 2</p>
|
|
634
|
+
</section>
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
---
|
|
638
|
+
|
|
639
|
+
## Icon Guidelines
|
|
640
|
+
|
|
641
|
+
**Lucide Icons** — Consistent 24px icons for UI
|
|
642
|
+
|
|
643
|
+
### Usage Patterns
|
|
644
|
+
|
|
645
|
+
- **Navigation:** Folder, File, Terminal, Settings icons
|
|
646
|
+
- **Actions:** Plus (add), Trash (delete), Check (confirm)
|
|
647
|
+
- **Status:** CheckCircle (success), XCircle (error), AlertCircle (warning)
|
|
648
|
+
- **Modifiers:** ChevronRight (expand), X (close)
|
|
649
|
+
|
|
650
|
+
```tsx
|
|
651
|
+
import { FileIcon, FolderIcon, TrashIcon } from "lucide-react";
|
|
652
|
+
|
|
653
|
+
<FileIcon className="w-5 h-5 text-gray-600" />
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### Size Guidelines
|
|
657
|
+
|
|
658
|
+
- **UI elements:** 16px–20px (inline, labels)
|
|
659
|
+
- **Buttons:** 20px–24px (primary actions)
|
|
660
|
+
- **Headers:** 32px+ (large, prominent)
|
|
661
|
+
|