@cluesmith/codev 1.4.1 → 1.4.2

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.
@@ -0,0 +1,314 @@
1
+ /* Tab Bar, Tab Buttons, Overflow Menu */
2
+
3
+ /* Tab bar */
4
+ .tab-bar {
5
+ display: flex;
6
+ align-items: center;
7
+ background: var(--bg-secondary);
8
+ border-bottom: 1px solid var(--border);
9
+ min-height: 40px;
10
+ overflow: visible; /* Allow overflow menu dropdown to be visible */
11
+ position: relative; /* Position context for overflow menu */
12
+ }
13
+
14
+ .tabs-scroll {
15
+ display: flex;
16
+ overflow-x: auto;
17
+ flex: 1;
18
+ scrollbar-width: none;
19
+ }
20
+
21
+ .tabs-scroll::-webkit-scrollbar {
22
+ display: none;
23
+ }
24
+
25
+ .tab {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: 6px;
29
+ padding: 8px 12px;
30
+ cursor: pointer;
31
+ border-right: 1px solid var(--border);
32
+ border-bottom: 2px solid transparent; /* Reserve space for active indicator */
33
+ white-space: nowrap;
34
+ flex-shrink: 0;
35
+ position: relative;
36
+ }
37
+
38
+ .tab:hover {
39
+ background: var(--tab-hover);
40
+ }
41
+
42
+ .tab.active {
43
+ background: var(--bg-tertiary);
44
+ border-bottom: 2px solid var(--accent); /* Blue accent line */
45
+ }
46
+
47
+ .tab.new-tab {
48
+ animation: tab-pulse 0.5s ease-out;
49
+ }
50
+
51
+ @keyframes tab-pulse {
52
+ 0% { background: var(--accent); }
53
+ 100% { background: var(--tab-active); }
54
+ }
55
+
56
+ .tab .icon {
57
+ font-size: 14px;
58
+ }
59
+
60
+ .tab .name {
61
+ font-size: 13px;
62
+ max-width: 120px;
63
+ overflow: hidden;
64
+ text-overflow: ellipsis;
65
+ color: var(--text-secondary);
66
+ }
67
+
68
+ .tab.active .name {
69
+ color: var(--text-primary);
70
+ }
71
+
72
+ .tab .status-dot {
73
+ width: 6px;
74
+ height: 6px;
75
+ border-radius: 50%;
76
+ }
77
+
78
+ /* Shape modifiers for accessibility (not just color) */
79
+ .tab .status-dot--diamond {
80
+ border-radius: 1px;
81
+ transform: rotate(45deg);
82
+ }
83
+
84
+ /* Ring shape for pr-ready (accessibility: distinct from circle) */
85
+ .tab .status-dot--ring {
86
+ box-shadow: inset 0 0 0 1.5px currentColor;
87
+ background: transparent !important;
88
+ color: var(--status-waiting);
89
+ }
90
+
91
+ /* Distinct animations per status category (spec 0019) */
92
+ @keyframes status-pulse {
93
+ /* Pulsing: Active/working (spawning, implementing) */
94
+ 0%, 100% { opacity: 1; transform: scale(1); }
95
+ 50% { opacity: 0.7; transform: scale(0.9); }
96
+ }
97
+
98
+ @keyframes status-blink-slow {
99
+ /* Slow blink: Idle/waiting (pr-ready) */
100
+ 0%, 100% { opacity: 1; }
101
+ 50% { opacity: 0.3; }
102
+ }
103
+
104
+ @keyframes status-blink-fast {
105
+ /* Fast blink: Error/blocked */
106
+ 0%, 100% { opacity: 1; }
107
+ 50% { opacity: 0.2; }
108
+ }
109
+
110
+ .tab .status-dot--pulse {
111
+ animation: status-pulse 2s ease-in-out infinite;
112
+ }
113
+
114
+ .tab .status-dot--blink-slow {
115
+ animation: status-blink-slow 3s ease-in-out infinite;
116
+ }
117
+
118
+ .tab .status-dot--blink-fast {
119
+ animation: status-blink-fast 0.8s ease-in-out infinite;
120
+ }
121
+
122
+ /* Respect reduced motion preference (WCAG 2.3.3) */
123
+ /* Motion-independent differentiators remain: diamond for blocked, ring for pr-ready */
124
+ @media (prefers-reduced-motion: reduce) {
125
+ .tab .status-dot--pulse,
126
+ .tab .status-dot--blink-slow,
127
+ .tab .status-dot--blink-fast {
128
+ animation: none;
129
+ }
130
+ }
131
+
132
+ .tab .close {
133
+ opacity: 0.6; /* Always clearly visible */
134
+ margin-left: 6px;
135
+ font-size: 16px;
136
+ font-weight: 500;
137
+ color: var(--text-secondary);
138
+ padding: 4px 8px;
139
+ border-radius: 4px;
140
+ cursor: pointer;
141
+ line-height: 1;
142
+ min-width: 24px;
143
+ min-height: 24px;
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ }
148
+
149
+ .tab:hover .close {
150
+ opacity: 0.9;
151
+ }
152
+
153
+ .tab .close:hover {
154
+ opacity: 1;
155
+ background: rgba(239, 68, 68, 0.2); /* Red tint on hover */
156
+ color: #ef4444;
157
+ }
158
+
159
+ /* Add buttons */
160
+ .add-buttons {
161
+ display: flex;
162
+ gap: 4px;
163
+ padding: 0 8px;
164
+ flex-shrink: 0;
165
+ }
166
+
167
+ .add-btn {
168
+ padding: 4px 8px;
169
+ border-radius: 4px;
170
+ border: 1px dashed var(--border);
171
+ background: transparent;
172
+ color: var(--text-muted);
173
+ cursor: pointer;
174
+ font-size: 12px;
175
+ display: flex;
176
+ align-items: center;
177
+ gap: 4px;
178
+ }
179
+
180
+ .add-btn:hover {
181
+ border-style: solid;
182
+ color: var(--text-secondary);
183
+ background: var(--bg-tertiary);
184
+ }
185
+
186
+ /* Overflow indicator */
187
+ .overflow-btn {
188
+ padding: 8px 12px;
189
+ background: var(--bg-tertiary);
190
+ border: none;
191
+ border-left: 1px solid var(--border);
192
+ color: var(--text-secondary);
193
+ cursor: pointer;
194
+ display: none; /* Hidden by default, shown via JS */
195
+ align-items: center;
196
+ gap: 4px;
197
+ flex-shrink: 0;
198
+ }
199
+
200
+ .overflow-btn:hover {
201
+ background: var(--tab-hover);
202
+ }
203
+
204
+ .overflow-btn:focus {
205
+ outline: 2px solid var(--accent);
206
+ outline-offset: -2px;
207
+ }
208
+
209
+ .overflow-count {
210
+ font-size: 11px;
211
+ background: var(--accent);
212
+ color: white;
213
+ padding: 1px 5px;
214
+ border-radius: 8px;
215
+ }
216
+
217
+ /* Overflow menu dropdown */
218
+ .overflow-menu {
219
+ position: absolute;
220
+ right: 0;
221
+ top: 100%;
222
+ background: var(--bg-secondary);
223
+ border: 1px solid var(--border);
224
+ border-radius: 4px;
225
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
226
+ max-height: 300px;
227
+ overflow-y: auto;
228
+ min-width: 200px;
229
+ z-index: 100;
230
+ }
231
+
232
+ .overflow-menu.hidden {
233
+ display: none;
234
+ }
235
+
236
+ .overflow-menu-item {
237
+ padding: 8px 12px;
238
+ cursor: pointer;
239
+ display: flex;
240
+ align-items: center;
241
+ gap: 8px;
242
+ font-size: 13px;
243
+ }
244
+
245
+ .overflow-menu-item:hover,
246
+ .overflow-menu-item:focus {
247
+ background: var(--tab-hover);
248
+ outline: none;
249
+ }
250
+
251
+ .overflow-menu-item.active {
252
+ background: var(--tab-active);
253
+ border-left: 2px solid var(--accent);
254
+ }
255
+
256
+ .overflow-menu-item .icon {
257
+ font-size: 14px;
258
+ }
259
+
260
+ .overflow-menu-item .name {
261
+ flex: 1;
262
+ overflow: hidden;
263
+ text-overflow: ellipsis;
264
+ white-space: nowrap;
265
+ }
266
+
267
+ .overflow-menu-item .open-external {
268
+ opacity: 0.5;
269
+ cursor: pointer;
270
+ padding: 2px 6px;
271
+ font-size: 12px;
272
+ border-radius: 3px;
273
+ }
274
+
275
+ .overflow-menu-item .open-external:hover {
276
+ opacity: 1;
277
+ background: rgba(255, 255, 255, 0.1);
278
+ }
279
+
280
+ /* Tab content */
281
+ .tab-content {
282
+ flex: 1;
283
+ display: flex;
284
+ flex-direction: column;
285
+ overflow: hidden;
286
+ }
287
+
288
+ .tab-content iframe {
289
+ flex: 1;
290
+ width: 100%;
291
+ border: none;
292
+ background: #000;
293
+ }
294
+
295
+ .empty-state {
296
+ flex: 1;
297
+ display: flex;
298
+ flex-direction: column;
299
+ align-items: center;
300
+ justify-content: center;
301
+ color: var(--text-muted);
302
+ gap: 12px;
303
+ }
304
+
305
+ .empty-state .hint {
306
+ font-size: 13px;
307
+ text-align: center;
308
+ max-width: 300px;
309
+ }
310
+
311
+ /* Projects tab without close button */
312
+ .tab.tab-uncloseable .close {
313
+ display: none;
314
+ }
@@ -0,0 +1,50 @@
1
+ /* Utility Classes and Miscellaneous Styles */
2
+
3
+ /* Hidden utility */
4
+ .hidden {
5
+ display: none !important;
6
+ }
7
+
8
+ /* Accessibility: Screen reader only */
9
+ .sr-only {
10
+ position: absolute;
11
+ width: 1px;
12
+ height: 1px;
13
+ padding: 0;
14
+ margin: -1px;
15
+ overflow: hidden;
16
+ clip: rect(0, 0, 0, 0);
17
+ white-space: nowrap;
18
+ border: 0;
19
+ }
20
+
21
+ /* Focus visible for keyboard navigation */
22
+ :focus-visible {
23
+ outline: 2px solid var(--accent);
24
+ outline-offset: 2px;
25
+ }
26
+
27
+ /* Scrollbar styling */
28
+ ::-webkit-scrollbar {
29
+ width: 8px;
30
+ height: 8px;
31
+ }
32
+
33
+ ::-webkit-scrollbar-track {
34
+ background: var(--bg-primary);
35
+ }
36
+
37
+ ::-webkit-scrollbar-thumb {
38
+ background: var(--border);
39
+ border-radius: 4px;
40
+ }
41
+
42
+ ::-webkit-scrollbar-thumb:hover {
43
+ background: var(--text-muted);
44
+ }
45
+
46
+ /* Selection color */
47
+ ::selection {
48
+ background: var(--accent);
49
+ color: white;
50
+ }
@@ -0,0 +1,45 @@
1
+ /* Dashboard CSS Variables */
2
+
3
+ * {
4
+ box-sizing: border-box;
5
+ margin: 0;
6
+ padding: 0;
7
+ }
8
+
9
+ :root {
10
+ --bg-primary: #1a1a1a;
11
+ --bg-secondary: #252525;
12
+ --bg-tertiary: #2a2a2a;
13
+ --border: #333;
14
+ --text-primary: #fff;
15
+ --text-secondary: #ccc;
16
+ --text-muted: #666;
17
+ --accent: #3b82f6;
18
+ --tab-active: #333;
19
+ --tab-hover: #2a2a2a;
20
+ /* Status indicator colors per spec 0019 */
21
+ --status-active: #22c55e; /* Green: spawning, implementing */
22
+ --status-waiting: #eab308; /* Yellow: pr-ready (waiting for review) */
23
+ --status-error: #ef4444; /* Red: blocked */
24
+ --status-complete: #9e9e9e; /* Gray: complete */
25
+ /* Project lifecycle status colors per spec 0045 */
26
+ --project-conceived: #eab308; /* Yellow */
27
+ --project-specified: #3b82f6; /* Blue */
28
+ --project-planned: #3b82f6; /* Blue */
29
+ --project-implementing: #f97316; /* Orange */
30
+ --project-implemented: #a855f7; /* Purple */
31
+ --project-committed: #22c55e; /* Green */
32
+ --project-integrated: #9e9e9e; /* Gray */
33
+ --project-abandoned: #ef4444; /* Red */
34
+ --project-on-hold: #9e9e9e; /* Gray */
35
+ }
36
+
37
+ body {
38
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
39
+ background: var(--bg-primary);
40
+ color: var(--text-primary);
41
+ height: 100vh;
42
+ display: flex;
43
+ flex-direction: column;
44
+ overflow: hidden;
45
+ }
@@ -0,0 +1,158 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Agent Farm - {{PROJECT_NAME}}</title>
7
+ <!-- CSS files loaded in dependency order -->
8
+ <link rel="stylesheet" href="/dashboard/css/variables.css">
9
+ <link rel="stylesheet" href="/dashboard/css/layout.css">
10
+ <link rel="stylesheet" href="/dashboard/css/tabs.css">
11
+ <link rel="stylesheet" href="/dashboard/css/statusbar.css">
12
+ <link rel="stylesheet" href="/dashboard/css/dialogs.css">
13
+ <link rel="stylesheet" href="/dashboard/css/activity.css">
14
+ <link rel="stylesheet" href="/dashboard/css/projects.css">
15
+ <link rel="stylesheet" href="/dashboard/css/files.css">
16
+ <link rel="stylesheet" href="/dashboard/css/utilities.css">
17
+ </head>
18
+ <body>
19
+ <header class="header">
20
+ <h1>Agent Farm - {{PROJECT_NAME}}</h1>
21
+ <div class="header-actions">
22
+ <button class="btn activity-summary-btn" onclick="showActivitySummary()" title="What did I do today?">
23
+ 🕐 Today
24
+ </button>
25
+ </div>
26
+ </header>
27
+
28
+ <main class="main">
29
+ <!-- Left pane: Architect terminal -->
30
+ <div class="left-pane">
31
+ <div class="pane-header">
32
+ <span class="status-dot" id="architect-status"></span>
33
+ <span>Architect</span>
34
+ </div>
35
+ <div id="architect-content"></div>
36
+ </div>
37
+
38
+ <!-- Right pane: Tabbed interface -->
39
+ <div class="right-pane">
40
+ <div class="tab-bar">
41
+ <div class="tabs-scroll" id="tabs-container"></div>
42
+ <button class="overflow-btn" id="overflow-btn" onclick="toggleOverflowMenu()" aria-haspopup="true" aria-expanded="false" title="Show all tabs">
43
+ <span>...</span>
44
+ <span class="overflow-count" id="overflow-count">+0</span>
45
+ </button>
46
+ <div class="overflow-menu hidden" id="overflow-menu" role="menu"></div>
47
+ </div>
48
+ <div class="tab-content" id="tab-content"></div>
49
+ </div>
50
+ </main>
51
+
52
+ <footer class="status-bar">
53
+ <div class="status-item" id="status-architect">
54
+ <span class="dot" style="background: var(--text-muted)"></span>
55
+ <span>Architect: stopped</span>
56
+ </div>
57
+ <div class="status-item" id="status-builders">
58
+ <span>0 builders</span>
59
+ </div>
60
+ <div class="status-item" id="status-shells">
61
+ <span>0 shells</span>
62
+ </div>
63
+ <div class="status-item" id="status-files">
64
+ <span>0 files</span>
65
+ </div>
66
+ </footer>
67
+
68
+ <!-- File picker dialog -->
69
+ <div class="dialog-overlay hidden" id="file-dialog">
70
+ <div class="dialog">
71
+ <h3>Open File</h3>
72
+ <div class="quick-paths">
73
+ <button class="quick-path" onclick="setFilePath('codev/specs/')">codev/specs/</button>
74
+ <button class="quick-path" onclick="setFilePath('codev/plans/')">codev/plans/</button>
75
+ <button class="quick-path" onclick="setFilePath('codev/reviews/')">codev/reviews/</button>
76
+ </div>
77
+ <input type="text" id="file-path-input" placeholder="Enter file path..." />
78
+ <div class="dialog-actions">
79
+ <button class="btn" onclick="hideFileDialog()">Cancel</button>
80
+ <button class="btn" onclick="openFile()">Open</button>
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Close confirmation dialog -->
86
+ <div class="dialog-overlay hidden" id="close-dialog">
87
+ <div class="dialog">
88
+ <h3 id="close-dialog-title">Close tab?</h3>
89
+ <p id="close-dialog-message" style="color: var(--text-secondary); margin-bottom: 16px; font-size: 14px;"></p>
90
+ <div class="dialog-actions">
91
+ <button class="btn" onclick="hideCloseDialog()">Cancel</button>
92
+ <button class="btn btn-danger" onclick="confirmClose()">Close</button>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- Context menu -->
98
+ <div class="context-menu hidden" id="context-menu" role="menu">
99
+ <div class="context-menu-item" role="menuitem" tabindex="0" data-action="openContextTab" onclick="openContextTab()" onkeydown="handleContextMenuKeydown(event)">Open in New Tab</div>
100
+ <div class="context-menu-item" role="menuitem" tabindex="-1" data-action="reloadContextTab" id="context-reload" onclick="reloadContextTab()" onkeydown="handleContextMenuKeydown(event)">Reload</div>
101
+ <div class="context-menu-item" role="menuitem" tabindex="-1" data-action="closeActiveTab" onclick="closeActiveTab()" onkeydown="handleContextMenuKeydown(event)">Close</div>
102
+ <div class="context-menu-item" role="menuitem" tabindex="-1" data-action="closeOtherTabs" onclick="closeOtherTabs()" onkeydown="handleContextMenuKeydown(event)">Close Others</div>
103
+ <div class="context-menu-item danger" role="menuitem" tabindex="-1" data-action="closeAllTabs" onclick="closeAllTabs()" onkeydown="handleContextMenuKeydown(event)">Close All</div>
104
+ </div>
105
+
106
+ <!-- Toast container -->
107
+ <div class="toast-container" id="toast-container"></div>
108
+
109
+ <!-- Activity Summary Modal (Spec 0059) -->
110
+ <div class="dialog-overlay hidden" id="activity-modal">
111
+ <div class="dialog activity-dialog">
112
+ <div class="activity-dialog-header">
113
+ <h3>Today's Summary</h3>
114
+ <button class="activity-close-btn" onclick="closeActivityModal()" title="Close (Esc)">×</button>
115
+ </div>
116
+ <div class="activity-dialog-content" id="activity-content">
117
+ <div class="activity-loading">
118
+ <span class="activity-spinner"></span>
119
+ Loading activity...
120
+ </div>
121
+ </div>
122
+ <div class="activity-dialog-footer">
123
+ <button class="btn" onclick="copyActivitySummary()">📋 Copy to Clipboard</button>
124
+ <button class="btn" onclick="closeActivityModal()">Close</button>
125
+ </div>
126
+ </div>
127
+ </div>
128
+
129
+ <!-- File search palette (Cmd+P) - Spec 0058 -->
130
+ <div id="file-palette" class="file-palette hidden">
131
+ <div class="file-palette-backdrop" onclick="closePalette()"></div>
132
+ <div class="file-palette-container">
133
+ <input type="text"
134
+ id="palette-input"
135
+ class="file-palette-input"
136
+ placeholder="Search files by name..."
137
+ oninput="onPaletteInput(this.value)"
138
+ onkeydown="onPaletteKeydown(event)" />
139
+ <div id="palette-results" class="file-palette-results"></div>
140
+ </div>
141
+ </div>
142
+
143
+ <!-- State injection (replaced by server) -->
144
+ <script>
145
+ // STATE_INJECTION_POINT
146
+ </script>
147
+
148
+ <!-- JavaScript files loaded in dependency order -->
149
+ <script src="/dashboard/js/state.js"></script>
150
+ <script src="/dashboard/js/utils.js"></script>
151
+ <script src="/dashboard/js/tabs.js"></script>
152
+ <script src="/dashboard/js/dialogs.js"></script>
153
+ <script src="/dashboard/js/projects.js"></script>
154
+ <script src="/dashboard/js/files.js"></script>
155
+ <script src="/dashboard/js/activity.js"></script>
156
+ <script src="/dashboard/js/main.js"></script>
157
+ </body>
158
+ </html>