reflectt-node 0.1.2 → 0.1.4

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,610 @@
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>Team Polls — Design Mock</title>
7
+ <style>
8
+ :root {
9
+ --bg: #0a0e14;
10
+ --surface: #141920;
11
+ --surface-raised: #1a2028;
12
+ --border: #252d38;
13
+ --border-subtle: #1e2530;
14
+ --text: #d4dae3;
15
+ --text-bright: #eef1f5;
16
+ --text-muted: #6b7a8d;
17
+ --accent: #4da6ff;
18
+ --accent-dim: rgba(77, 166, 255, 0.12);
19
+ --green: #3fb950;
20
+ --green-dim: rgba(63, 185, 80, 0.12);
21
+ --yellow: #d4a017;
22
+ --yellow-dim: rgba(212, 160, 23, 0.12);
23
+ --purple: #b48eff;
24
+ --purple-dim: rgba(180, 142, 255, 0.12);
25
+ --red: #f85149;
26
+ --radius-sm: 6px;
27
+ --radius-md: 8px;
28
+ --radius-lg: 14px;
29
+ --space-1: 4px;
30
+ --space-2: 8px;
31
+ --space-3: 12px;
32
+ --space-4: 16px;
33
+ --space-5: 20px;
34
+ --space-6: 24px;
35
+ --text-xs: 10px;
36
+ --text-sm: 11px;
37
+ --text-base: 13px;
38
+ --text-md: 14px;
39
+ --text-lg: 16px;
40
+ --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
41
+ --font-weight-normal: 400;
42
+ --font-weight-medium: 500;
43
+ --font-weight-semibold: 600;
44
+ --font-weight-bold: 700;
45
+ --focus-ring: 0 0 0 2px rgba(77, 166, 255, 0.5);
46
+ --transition-fast: 150ms;
47
+ --easing-smooth: cubic-bezier(0.4, 0, 0.2, 1);
48
+ }
49
+
50
+ * { box-sizing: border-box; margin: 0; padding: 0; }
51
+
52
+ body {
53
+ font-family: var(--font-family);
54
+ background: var(--bg);
55
+ color: var(--text);
56
+ min-height: 100vh;
57
+ display: flex;
58
+ flex-direction: column;
59
+ align-items: center;
60
+ padding: 40px 20px;
61
+ -webkit-font-smoothing: antialiased;
62
+ }
63
+
64
+ h1 { font-size: 18px; font-weight: 700; color: var(--text-bright); margin-bottom: 6px; }
65
+ .subtitle { font-size: var(--text-base); color: var(--text-muted); margin-bottom: 32px; }
66
+
67
+ .demo-grid {
68
+ display: grid;
69
+ grid-template-columns: 1fr 1fr;
70
+ gap: 24px;
71
+ max-width: 800px;
72
+ width: 100%;
73
+ }
74
+ @media (max-width: 640px) { .demo-grid { grid-template-columns: 1fr; } }
75
+
76
+ .demo-label {
77
+ font-size: var(--text-xs);
78
+ text-transform: uppercase;
79
+ letter-spacing: 0.8px;
80
+ color: var(--text-muted);
81
+ font-weight: var(--font-weight-semibold);
82
+ margin-bottom: var(--space-2);
83
+ margin-top: var(--space-4);
84
+ }
85
+
86
+ /* === Panel (reuse dashboard pattern) === */
87
+ .panel {
88
+ background: var(--surface);
89
+ border: 1px solid var(--border);
90
+ border-radius: var(--radius-md);
91
+ overflow: hidden;
92
+ }
93
+ .panel-header {
94
+ padding: var(--space-3) var(--space-4);
95
+ border-bottom: 1px solid var(--border);
96
+ font-size: var(--text-md);
97
+ font-weight: var(--font-weight-semibold);
98
+ color: var(--text-bright);
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: space-between;
102
+ }
103
+ .panel-body { padding: var(--space-4); }
104
+
105
+ /* === Poll Card === */
106
+ .poll-card {
107
+ background: var(--surface-raised);
108
+ border: 1px solid var(--border);
109
+ border-radius: var(--radius-sm);
110
+ padding: var(--space-4);
111
+ margin-bottom: var(--space-3);
112
+ }
113
+ .poll-card:last-child { margin-bottom: 0; }
114
+ .poll-question {
115
+ font-size: var(--text-md);
116
+ font-weight: var(--font-weight-semibold);
117
+ color: var(--text-bright);
118
+ margin-bottom: var(--space-3);
119
+ line-height: 1.4;
120
+ }
121
+ .poll-meta {
122
+ display: flex;
123
+ align-items: center;
124
+ gap: var(--space-2);
125
+ font-size: var(--text-xs);
126
+ color: var(--text-muted);
127
+ margin-bottom: var(--space-3);
128
+ }
129
+ .poll-author {
130
+ color: var(--accent);
131
+ font-weight: var(--font-weight-semibold);
132
+ }
133
+ .poll-status {
134
+ padding: 1px 6px;
135
+ border-radius: 999px;
136
+ font-size: 9px;
137
+ font-weight: 700;
138
+ text-transform: uppercase;
139
+ letter-spacing: 0.3px;
140
+ }
141
+ .poll-status.open { background: var(--green-dim); color: var(--green); }
142
+ .poll-status.closed { background: var(--border); color: var(--text-muted); }
143
+
144
+ /* === Vote Options === */
145
+ .poll-options { display: flex; flex-direction: column; gap: 6px; }
146
+ .poll-option {
147
+ position: relative;
148
+ display: flex;
149
+ align-items: center;
150
+ gap: var(--space-3);
151
+ padding: var(--space-2) var(--space-3);
152
+ border: 1px solid var(--border);
153
+ border-radius: var(--radius-sm);
154
+ cursor: pointer;
155
+ transition: all var(--transition-fast) var(--easing-smooth);
156
+ min-height: 40px;
157
+ overflow: hidden;
158
+ }
159
+ .poll-option:focus-visible {
160
+ outline: none;
161
+ box-shadow: var(--focus-ring);
162
+ }
163
+ .poll-option .bar {
164
+ position: absolute;
165
+ top: 0;
166
+ left: 0;
167
+ height: 100%;
168
+ border-radius: var(--radius-sm);
169
+ transition: width 400ms var(--easing-smooth);
170
+ z-index: 0;
171
+ }
172
+ .poll-option .bar.accent { background: var(--accent-dim); }
173
+ .poll-option .bar.green { background: var(--green-dim); }
174
+ .poll-option .bar.purple { background: var(--purple-dim); }
175
+ .poll-option .bar.yellow { background: var(--yellow-dim); }
176
+
177
+ .poll-option .option-content {
178
+ position: relative;
179
+ z-index: 1;
180
+ display: flex;
181
+ align-items: center;
182
+ justify-content: space-between;
183
+ width: 100%;
184
+ gap: var(--space-2);
185
+ }
186
+ .poll-option .option-label {
187
+ font-size: var(--text-base);
188
+ color: var(--text);
189
+ font-weight: var(--font-weight-medium);
190
+ }
191
+ .poll-option .option-right {
192
+ display: flex;
193
+ align-items: center;
194
+ gap: var(--space-2);
195
+ flex-shrink: 0;
196
+ }
197
+ .poll-option .vote-count {
198
+ font-size: var(--text-sm);
199
+ color: var(--text-muted);
200
+ font-weight: var(--font-weight-semibold);
201
+ min-width: 20px;
202
+ text-align: right;
203
+ }
204
+ .poll-option .vote-pct {
205
+ font-size: var(--text-xs);
206
+ color: var(--text-muted);
207
+ min-width: 28px;
208
+ text-align: right;
209
+ }
210
+ .poll-option .voters {
211
+ display: flex;
212
+ gap: 2px;
213
+ }
214
+ .poll-option .voter-dot {
215
+ width: 18px;
216
+ height: 18px;
217
+ border-radius: 50%;
218
+ font-size: 10px;
219
+ display: flex;
220
+ align-items: center;
221
+ justify-content: center;
222
+ background: var(--border);
223
+ color: var(--text-muted);
224
+ font-weight: 700;
225
+ border: 1px solid var(--surface-raised);
226
+ }
227
+ .poll-option.voted {
228
+ border-color: var(--accent);
229
+ background: rgba(77, 166, 255, 0.04);
230
+ }
231
+ .poll-option .check {
232
+ width: 18px;
233
+ height: 18px;
234
+ border-radius: 50%;
235
+ border: 2px solid var(--border);
236
+ flex-shrink: 0;
237
+ transition: all var(--transition-fast);
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ font-size: 11px;
242
+ }
243
+ .poll-option.voted .check {
244
+ background: var(--accent);
245
+ border-color: var(--accent);
246
+ color: #fff;
247
+ }
248
+
249
+ @media (hover: hover) and (pointer: fine) {
250
+ .poll-option:hover:not(.voted) {
251
+ border-color: var(--accent);
252
+ background: rgba(77, 166, 255, 0.03);
253
+ }
254
+ }
255
+
256
+ /* === Poll Footer === */
257
+ .poll-footer {
258
+ display: flex;
259
+ align-items: center;
260
+ justify-content: space-between;
261
+ margin-top: var(--space-3);
262
+ font-size: var(--text-xs);
263
+ color: var(--text-muted);
264
+ }
265
+ .poll-total { font-weight: var(--font-weight-semibold); }
266
+
267
+ /* === Create Poll Form === */
268
+ .create-poll { padding: var(--space-4); }
269
+ .create-poll .form-group { margin-bottom: var(--space-3); }
270
+ .create-poll label {
271
+ display: block;
272
+ font-size: var(--text-sm);
273
+ font-weight: var(--font-weight-medium);
274
+ color: var(--text-muted);
275
+ margin-bottom: var(--space-1);
276
+ }
277
+ .create-poll input, .create-poll textarea {
278
+ width: 100%;
279
+ padding: var(--space-2) var(--space-3);
280
+ background: var(--bg);
281
+ border: 1px solid var(--border);
282
+ border-radius: var(--radius-sm);
283
+ color: var(--text);
284
+ font-family: inherit;
285
+ font-size: var(--text-base);
286
+ }
287
+ .create-poll input:focus, .create-poll textarea:focus {
288
+ outline: none;
289
+ border-color: var(--accent);
290
+ box-shadow: var(--focus-ring);
291
+ }
292
+ .create-poll input::placeholder { color: var(--text-muted); }
293
+ .option-inputs { display: flex; flex-direction: column; gap: var(--space-2); }
294
+ .option-row {
295
+ display: flex;
296
+ gap: var(--space-2);
297
+ align-items: center;
298
+ }
299
+ .option-row input { flex: 1; }
300
+ .remove-option {
301
+ width: 28px;
302
+ height: 28px;
303
+ border-radius: var(--radius-sm);
304
+ border: 1px solid var(--border);
305
+ background: transparent;
306
+ color: var(--text-muted);
307
+ cursor: pointer;
308
+ font-size: 14px;
309
+ display: flex;
310
+ align-items: center;
311
+ justify-content: center;
312
+ transition: all var(--transition-fast);
313
+ }
314
+ @media (hover: hover) and (pointer: fine) {
315
+ .remove-option:hover { border-color: var(--red); color: var(--red); }
316
+ }
317
+ .add-option-btn {
318
+ display: flex;
319
+ align-items: center;
320
+ gap: var(--space-1);
321
+ padding: var(--space-2) var(--space-3);
322
+ border: 1px dashed var(--border);
323
+ border-radius: var(--radius-sm);
324
+ background: transparent;
325
+ color: var(--text-muted);
326
+ font-size: var(--text-sm);
327
+ cursor: pointer;
328
+ font-family: inherit;
329
+ width: 100%;
330
+ justify-content: center;
331
+ transition: all var(--transition-fast);
332
+ }
333
+ @media (hover: hover) and (pointer: fine) {
334
+ .add-option-btn:hover { border-color: var(--accent); color: var(--accent); }
335
+ }
336
+ .form-actions {
337
+ display: flex;
338
+ gap: var(--space-2);
339
+ margin-top: var(--space-4);
340
+ }
341
+ .btn {
342
+ display: inline-flex;
343
+ align-items: center;
344
+ gap: 6px;
345
+ padding: 8px 16px;
346
+ border-radius: var(--radius-sm);
347
+ font-size: var(--text-base);
348
+ font-weight: var(--font-weight-semibold);
349
+ font-family: inherit;
350
+ cursor: pointer;
351
+ border: 1px solid var(--border);
352
+ background: var(--bg);
353
+ color: var(--text);
354
+ transition: all var(--transition-fast) var(--easing-smooth);
355
+ }
356
+ .btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
357
+ .btn-primary { background: var(--accent); color: #fff; border-color: var(--accent); }
358
+ @media (hover: hover) and (pointer: fine) {
359
+ .btn-primary:hover { opacity: 0.85; }
360
+ .btn:hover:not(.btn-primary) { border-color: var(--accent); color: var(--accent); }
361
+ }
362
+
363
+ /* === Settings Row === */
364
+ .settings-row {
365
+ display: flex;
366
+ align-items: center;
367
+ gap: var(--space-3);
368
+ margin-top: var(--space-3);
369
+ font-size: var(--text-sm);
370
+ color: var(--text-muted);
371
+ }
372
+ .settings-row select {
373
+ padding: 4px 8px;
374
+ background: var(--bg);
375
+ border: 1px solid var(--border);
376
+ border-radius: var(--radius-sm);
377
+ color: var(--text);
378
+ font-family: inherit;
379
+ font-size: var(--text-sm);
380
+ }
381
+
382
+ /* === Mock Footer === */
383
+ .mock-footer {
384
+ margin-top: 40px;
385
+ font-size: var(--text-xs);
386
+ color: var(--text-muted);
387
+ text-align: center;
388
+ }
389
+
390
+ /* Full-width section */
391
+ .full-width {
392
+ grid-column: 1 / -1;
393
+ }
394
+ </style>
395
+ </head>
396
+ <body>
397
+
398
+ <h1>🗳️ Team Polls</h1>
399
+ <p class="subtitle">Design mock — agents + humans create, vote, and see results</p>
400
+
401
+ <div class="demo-grid">
402
+ <!-- Left: Active polls -->
403
+ <div>
404
+ <div class="demo-label">Active Poll (with results)</div>
405
+ <div class="panel">
406
+ <div class="panel-header">
407
+ 🗳️ Polls
408
+ <button class="btn" onclick="document.getElementById('create-form').style.display = document.getElementById('create-form').style.display === 'none' ? 'block' : 'none'" style="font-size:11px;padding:4px 10px">+ New Poll</button>
409
+ </div>
410
+ <div class="panel-body" style="padding:0">
411
+
412
+ <!-- Poll 1: Active, partially voted -->
413
+ <div class="poll-card" id="poll1">
414
+ <div class="poll-meta">
415
+ <span class="poll-author">@kai</span>
416
+ <span>·</span>
417
+ <span>2h ago</span>
418
+ <span class="poll-status open">Open</span>
419
+ </div>
420
+ <div class="poll-question">Should we prioritize the bootstrap page or the cloud dashboard this sprint?</div>
421
+ <div class="poll-options" id="poll1-options">
422
+ <button class="poll-option voted" data-option="0" onclick="vote('poll1', 0)" role="radio" aria-checked="true">
423
+ <div class="bar accent" style="width: 60%"></div>
424
+ <div class="check">✓</div>
425
+ <div class="option-content">
426
+ <span class="option-label">Bootstrap page — it's the funnel</span>
427
+ <div class="option-right">
428
+ <div class="voters">
429
+ <span class="voter-dot" title="ryan" style="background:var(--green-dim);color:var(--green)">R</span>
430
+ <span class="voter-dot" title="pixel" style="background:var(--accent-dim);color:var(--accent)">P</span>
431
+ <span class="voter-dot" title="link" style="background:var(--purple-dim);color:var(--purple)">L</span>
432
+ </div>
433
+ <span class="vote-count">3</span>
434
+ <span class="vote-pct">60%</span>
435
+ </div>
436
+ </div>
437
+ </button>
438
+ <button class="poll-option" data-option="1" onclick="vote('poll1', 1)" role="radio" aria-checked="false">
439
+ <div class="bar purple" style="width: 40%"></div>
440
+ <div class="check"></div>
441
+ <div class="option-content">
442
+ <span class="option-label">Cloud dashboard — existing users need it</span>
443
+ <div class="option-right">
444
+ <div class="voters">
445
+ <span class="voter-dot" title="sage" style="background:var(--yellow-dim);color:var(--yellow)">S</span>
446
+ <span class="voter-dot" title="spark" style="background:var(--border);color:var(--text-muted)">Sp</span>
447
+ </div>
448
+ <span class="vote-count">2</span>
449
+ <span class="vote-pct">40%</span>
450
+ </div>
451
+ </div>
452
+ </button>
453
+ </div>
454
+ <div class="poll-footer">
455
+ <span class="poll-total">5 votes</span>
456
+ <span>Closes in 22h</span>
457
+ </div>
458
+ </div>
459
+
460
+ <!-- Poll 2: Closed -->
461
+ <div class="poll-card">
462
+ <div class="poll-meta">
463
+ <span class="poll-author">@spark</span>
464
+ <span>·</span>
465
+ <span>yesterday</span>
466
+ <span class="poll-status closed">Closed</span>
467
+ </div>
468
+ <div class="poll-question">Agent intensity: what should the default be for new installs?</div>
469
+ <div class="poll-options">
470
+ <div class="poll-option" style="cursor:default">
471
+ <div class="bar green" style="width: 71%"></div>
472
+ <div class="option-content">
473
+ <span class="option-label">⚡ Normal</span>
474
+ <div class="option-right">
475
+ <span class="vote-count">5</span>
476
+ <span class="vote-pct">71%</span>
477
+ </div>
478
+ </div>
479
+ </div>
480
+ <div class="poll-option" style="cursor:default">
481
+ <div class="bar yellow" style="width: 29%"></div>
482
+ <div class="option-content">
483
+ <span class="option-label">🐢 Low</span>
484
+ <div class="option-right">
485
+ <span class="vote-count">2</span>
486
+ <span class="vote-pct">29%</span>
487
+ </div>
488
+ </div>
489
+ </div>
490
+ <div class="poll-option" style="cursor:default">
491
+ <div class="bar" style="width: 0%"></div>
492
+ <div class="option-content">
493
+ <span class="option-label">🔥 High</span>
494
+ <div class="option-right">
495
+ <span class="vote-count">0</span>
496
+ <span class="vote-pct">0%</span>
497
+ </div>
498
+ </div>
499
+ </div>
500
+ </div>
501
+ <div class="poll-footer">
502
+ <span class="poll-total">7 votes · decided</span>
503
+ <span>Winner: ⚡ Normal</span>
504
+ </div>
505
+ </div>
506
+ </div>
507
+ </div>
508
+ </div>
509
+
510
+ <!-- Right: Create poll form -->
511
+ <div>
512
+ <div class="demo-label">Create New Poll</div>
513
+ <div class="panel">
514
+ <div class="panel-header">📝 New Poll</div>
515
+ <div class="create-poll" id="create-form">
516
+ <div class="form-group">
517
+ <label>Question</label>
518
+ <input type="text" placeholder="What should we decide?" />
519
+ </div>
520
+ <div class="form-group">
521
+ <label>Options</label>
522
+ <div class="option-inputs" id="option-inputs">
523
+ <div class="option-row">
524
+ <input type="text" placeholder="Option 1" />
525
+ <button class="remove-option" title="Remove">×</button>
526
+ </div>
527
+ <div class="option-row">
528
+ <input type="text" placeholder="Option 2" />
529
+ <button class="remove-option" title="Remove">×</button>
530
+ </div>
531
+ <div class="option-row">
532
+ <input type="text" placeholder="Option 3 (optional)" />
533
+ <button class="remove-option" title="Remove">×</button>
534
+ </div>
535
+ </div>
536
+ <button class="add-option-btn" onclick="addOption()">+ Add option</button>
537
+ </div>
538
+ <div class="settings-row">
539
+ <span>Expires in:</span>
540
+ <select>
541
+ <option>1 hour</option>
542
+ <option>4 hours</option>
543
+ <option selected>24 hours</option>
544
+ <option>3 days</option>
545
+ <option>Never</option>
546
+ </select>
547
+ <span>|</span>
548
+ <label style="display:inline-flex;align-items:center;gap:4px;cursor:pointer">
549
+ <input type="checkbox" /> Anonymous
550
+ </label>
551
+ </div>
552
+ <div class="form-actions">
553
+ <button class="btn btn-primary">Create Poll</button>
554
+ <button class="btn">Cancel</button>
555
+ </div>
556
+ </div>
557
+ </div>
558
+
559
+ <div class="demo-label" style="margin-top:24px">API: Create via CLI / agents</div>
560
+ <div class="panel">
561
+ <div class="panel-body" style="font-family:monospace;font-size:11px;color:var(--accent);white-space:pre;overflow-x:auto;line-height:1.6">POST /polls
562
+ {
563
+ "question": "Should we ship X?",
564
+ "options": ["Yes", "No", "Defer"],
565
+ "author": "kai",
566
+ "expires_in": "24h",
567
+ "anonymous": false
568
+ }
569
+
570
+ POST /polls/:id/vote
571
+ { "voter": "pixel", "option": 0 }
572
+
573
+ GET /polls?status=open</div>
574
+ </div>
575
+ </div>
576
+ </div>
577
+
578
+ <div class="mock-footer">
579
+ Design mock by pixel 🎨 · task-1772249879438-u7edc3c9y · reflectt-node<br>
580
+ <strong>Placement:</strong> Sidebar nav → "Polls" page (#polls) or embedded in Overview page
581
+ </div>
582
+
583
+ <script>
584
+ let optionCount = 3;
585
+
586
+ function addOption() {
587
+ optionCount++;
588
+ const row = document.createElement('div');
589
+ row.className = 'option-row';
590
+ row.innerHTML = `<input type="text" placeholder="Option ${optionCount}" /><button class="remove-option" title="Remove" onclick="this.parentElement.remove()">×</button>`;
591
+ document.getElementById('option-inputs').appendChild(row);
592
+ }
593
+
594
+ function vote(pollId, optionIdx) {
595
+ const options = document.querySelectorAll(`#${pollId}-options .poll-option`);
596
+ options.forEach((opt, i) => {
597
+ if (i === optionIdx) {
598
+ opt.classList.add('voted');
599
+ opt.setAttribute('aria-checked', 'true');
600
+ opt.querySelector('.check').textContent = '✓';
601
+ } else {
602
+ opt.classList.remove('voted');
603
+ opt.setAttribute('aria-checked', 'false');
604
+ opt.querySelector('.check').textContent = '';
605
+ }
606
+ });
607
+ }
608
+ </script>
609
+ </body>
610
+ </html>