gabriel / musehub public
_proposals.scss
550 lines 14.3 KB
Raw
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ breaking 156 days ago
1 // _proposals.scss — Proposals list page (.prl-* prefix)
2
3 // ── State palette ──────────────────────────────────────────────────────────────
4 $proposal-open: #3fb950;
5 $proposal-merged: #a371f7;
6 $proposal-closed: #f85149;
7
8 // ── Page shell ─────────────────────────────────────────────────────────────────
9 .prl-page {
10 display: flex;
11 flex-direction: column;
12 }
13
14 // ── Hero ───────────────────────────────────────────────────────────────────────
15 .prl-hero {
16 position: relative;
17 overflow: hidden;
18 background: linear-gradient(to bottom, color-mix(in srgb, var(--bg-canvas) 60%, transparent) 0%, var(--bg-surface) 100%);
19 border-bottom: 1px solid var(--border-default);
20 padding: var(--space-10) var(--space-8) var(--space-8);
21 }
22
23 .prl-hero-glow {
24 position: absolute;
25 inset: 0;
26 pointer-events: none;
27 opacity: 0.06;
28
29 &--open { background: radial-gradient(ellipse 55% 60% at 15% 0%, #{$proposal-open} 0%, transparent 70%); }
30 &--merged { background: radial-gradient(ellipse 55% 60% at 15% 0%, #{$proposal-merged} 0%, transparent 70%); }
31 &--closed { background: radial-gradient(ellipse 55% 60% at 15% 0%, #{$proposal-closed} 0%, transparent 70%); }
32 &--all { background: radial-gradient(ellipse 55% 60% at 15% 0%, var(--color-accent) 0%, transparent 70%); }
33 }
34
35 .prl-hero-inner {
36 position: relative;
37 max-width: 960px;
38 display: flex;
39 flex-wrap: wrap;
40 align-items: flex-end;
41 gap: var(--space-6);
42 }
43
44 // Copy — eyebrow + title + subtitle
45 .prl-hero-copy {
46 flex: 1;
47 min-width: 260px;
48 display: flex;
49 flex-direction: column;
50 gap: var(--space-2);
51 }
52
53 .prl-hero-eyebrow {
54 display: inline-flex;
55 align-items: center;
56 gap: 6px;
57 font-size: 11px;
58 font-weight: var(--font-weight-medium);
59 color: var(--text-muted);
60 text-transform: uppercase;
61 letter-spacing: 0.07em;
62 margin-bottom: var(--space-1);
63 }
64
65 .prl-hero-title {
66 font-size: 28px;
67 font-weight: var(--font-weight-bold);
68 color: var(--text-primary);
69 line-height: 1.15;
70 margin: 0;
71 letter-spacing: -0.02em;
72 }
73
74 .prl-hero-sub {
75 font-size: 13px;
76 color: var(--text-muted);
77 line-height: 1.55;
78 margin: 0;
79 max-width: 440px;
80 }
81
82 // Hero CTA
83 .prl-hero-actions {
84 align-self: flex-start;
85 flex-shrink: 0;
86 }
87
88 .prl-new-btn {
89 display: inline-flex;
90 align-items: center;
91 gap: 7px;
92 padding: 8px 16px;
93 font-size: 13px;
94 font-weight: var(--font-weight-semibold);
95 color: var(--text-primary);
96 background: transparent;
97 border: 1px solid var(--border-default);
98 border-radius: var(--radius-md);
99 text-decoration: none;
100 transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
101
102 &:hover {
103 text-decoration: none;
104 border-color: var(--color-accent);
105 color: var(--color-accent);
106 background: color-mix(in srgb, var(--color-accent) 7%, transparent);
107 }
108 }
109
110 // ── Filter / sort bar ──────────────────────────────────────────────────────────
111 .prl-filterbar {
112 display: flex;
113 align-items: stretch;
114 border-bottom: 1px solid var(--border-subtle);
115 background: var(--bg-surface);
116 padding: 0 var(--space-6);
117 gap: 0;
118 min-height: 44px;
119 }
120
121 .prl-tabs {
122 display: flex;
123 flex: 1;
124 gap: 0;
125 overflow-x: auto;
126 scrollbar-width: none;
127 &::-webkit-scrollbar { display: none; }
128 }
129
130 .prl-tab {
131 display: inline-flex;
132 align-items: center;
133 gap: 6px;
134 padding: 0 14px;
135 font-size: 12px;
136 font-weight: var(--font-weight-medium);
137 color: var(--text-muted);
138 text-decoration: none;
139 border-bottom: 2px solid transparent;
140 white-space: nowrap;
141 transition: color var(--transition-fast), border-color var(--transition-fast);
142 min-height: 44px;
143
144 &:hover { color: var(--text-secondary); text-decoration: none; }
145
146 &--active {
147 color: var(--text-primary);
148 border-bottom-color: var(--color-accent);
149 font-weight: var(--font-weight-semibold);
150 }
151 }
152
153 .prl-tab-pip {
154 width: 7px;
155 height: 7px;
156 border-radius: 50%;
157 flex-shrink: 0;
158 &--open { background: $proposal-open; }
159 &--merged { background: $proposal-merged; }
160 &--closed { background: $proposal-closed; }
161 }
162
163 .prl-tab-ct {
164 background: var(--bg-overlay);
165 border: 1px solid var(--border-subtle);
166 border-radius: var(--radius-full);
167 font-size: 10px;
168 font-weight: var(--font-weight-semibold);
169 font-family: var(--font-mono);
170 padding: 1px 5px;
171 min-width: 16px;
172 text-align: center;
173 color: var(--text-muted);
174 }
175
176 .prl-sort {
177 display: flex;
178 align-items: center;
179 gap: var(--space-2);
180 flex-shrink: 0;
181 padding-left: var(--space-4);
182 border-left: 1px solid var(--border-subtle);
183 margin: 8px 0;
184 }
185
186 .prl-sort-label {
187 font-size: 11px;
188 color: var(--text-muted);
189 margin-right: 2px;
190 }
191
192 .prl-sort-opt {
193 font-size: 12px;
194 color: var(--text-muted);
195 text-decoration: none;
196 padding: 2px 7px;
197 border-radius: var(--radius-sm);
198 transition: background var(--transition-fast), color var(--transition-fast);
199
200 &:hover { color: var(--text-secondary); text-decoration: none; }
201
202 &--active {
203 color: var(--text-primary);
204 font-weight: var(--font-weight-semibold);
205 background: var(--bg-overlay);
206 border: 1px solid var(--border-subtle);
207 }
208 }
209
210 // ── Proposal list ────────────────────────────────────────────────────────────────────
211 .prl-list {
212 display: flex;
213 flex-direction: column;
214 }
215
216 // ── Proposal row ─────────────────────────────────────────────────────────────────────
217 .prl-row {
218 display: flex;
219 align-items: center;
220 gap: var(--space-4);
221 padding: 12px var(--space-6);
222 border-bottom: 1px solid var(--border-subtle);
223 border-left: 3px solid transparent;
224 text-decoration: none;
225 cursor: pointer;
226 transition: background var(--transition-fast), border-left-color var(--transition-fast);
227
228 &:last-child { border-bottom: none; }
229
230 &:hover {
231 background: var(--bg-overlay);
232 text-decoration: none;
233 }
234
235 // State accent on the left border — subtle until hover
236 &--open:hover { border-left-color: $proposal-open; }
237 &--merged:hover { border-left-color: $proposal-merged; }
238 &--closed:hover { border-left-color: $proposal-closed; }
239
240 // Always show on merged/closed (they're done states)
241 &--merged { border-left-color: color-mix(in srgb, #{$proposal-merged} 35%, transparent); }
242 &--closed { border-left-color: color-mix(in srgb, #{$proposal-closed} 25%, transparent); }
243 }
244
245 // Row body — takes all remaining space
246 .prl-row-body {
247 flex: 1;
248 min-width: 0;
249 display: flex;
250 flex-direction: column;
251 gap: 4px;
252 }
253
254 // Title row
255 .prl-row-hd {
256 display: flex;
257 align-items: baseline;
258 gap: 7px;
259 flex-wrap: wrap;
260 }
261
262 .prl-row-title {
263 font-size: 14px;
264 font-weight: var(--font-weight-semibold);
265 color: var(--text-primary);
266 line-height: 1.4;
267 }
268
269 // Commit-type badge
270 .prl-badge {
271 display: inline-block;
272 font-size: 10px;
273 font-weight: var(--font-weight-bold);
274 font-family: var(--font-mono);
275 padding: 1px 5px;
276 border-radius: var(--radius-sm);
277 text-transform: lowercase;
278 letter-spacing: 0.02em;
279 background: rgba(88, 166, 255, 0.1);
280 color: #58a6ff;
281 border: 1px solid rgba(88, 166, 255, 0.22);
282 flex-shrink: 0;
283
284 &[data-type="feat"],
285 &[data-type="feature"] { background: rgba(63, 185, 80, 0.1); color: $proposal-open; border-color: rgba(63, 185, 80, 0.22); }
286 &[data-type="fix"],
287 &[data-type="bugfix"],
288 &[data-type="hotfix"] { background: rgba(248, 81, 73, 0.1); color: $proposal-closed; border-color: rgba(248, 81, 73, 0.22); }
289 &[data-type="refactor"] { background: rgba(163, 113, 247, 0.1); color: $proposal-merged; border-color: rgba(163, 113, 247, 0.22); }
290 &[data-type="docs"] { background: rgba(227, 179, 65, 0.1); color: #e3b341; border-color: rgba(227, 179, 65, 0.22); }
291 &[data-type="test"] { background: rgba(45, 212, 191, 0.1); color: #2dd4bf; border-color: rgba(45, 212, 191, 0.22); }
292 &[data-type="chore"],
293 &[data-type="style"] { background: rgba(139, 148, 158, 0.1); color: #8b949e; border-color: rgba(139, 148, 158, 0.22); }
294 &[data-type="redesign"] { background: rgba(245, 158, 11, 0.1); color: #f59e0b; border-color: rgba(245, 158, 11, 0.22); }
295 &[data-type="breaking"],
296 &[data-type="major"] { background: rgba(248, 81, 73, 0.15); color: $proposal-closed; border-color: rgba(248, 81, 73, 0.3); font-weight: var(--font-weight-black); }
297 }
298
299 // Semantic version impact pill
300 .prl-impact {
301 display: inline-block;
302 font-size: 9px;
303 font-weight: var(--font-weight-black);
304 font-family: var(--font-mono);
305 padding: 1px 4px;
306 border-radius: 2px;
307 text-transform: uppercase;
308 letter-spacing: 0.06em;
309 flex-shrink: 0;
310
311 &--major { background: rgba(248, 81, 73, 0.15); color: $proposal-closed; }
312 &--minor { background: rgba(63, 185, 80, 0.12); color: $proposal-open; }
313 &--patch { background: rgba(139, 148, 158, 0.12); color: #8b949e; }
314 }
315
316 // Meta row
317 .prl-row-meta {
318 display: flex;
319 align-items: center;
320 flex-wrap: wrap;
321 gap: 5px;
322 font-size: 11px;
323 color: var(--text-muted);
324 min-width: 0;
325 }
326
327 .prl-branch {
328 display: inline-flex;
329 align-items: center;
330 gap: 3px;
331 font-size: 11px;
332 font-family: var(--font-mono);
333 color: var(--text-muted);
334 background: var(--bg-overlay);
335 border: 1px solid var(--border-subtle);
336 border-radius: var(--radius-sm);
337 padding: 1px 5px;
338 max-width: 200px;
339 overflow: hidden;
340 text-overflow: ellipsis;
341 white-space: nowrap;
342
343 &--from {
344 color: #58a6ff;
345 border-color: rgba(88, 166, 255, 0.22);
346 background: rgba(88, 166, 255, 0.07);
347 }
348 }
349
350 .prl-arrow {
351 flex-shrink: 0;
352 color: var(--text-muted);
353 opacity: 0.5;
354 }
355
356 .prl-meta-dot {
357 opacity: 0.3;
358 flex-shrink: 0;
359 }
360
361 .prl-actor {
362 display: inline-flex;
363 align-items: center;
364 gap: 4px;
365 color: var(--text-secondary);
366 font-weight: var(--font-weight-medium);
367 flex-shrink: 0;
368 }
369
370 .prl-avatar {
371 width: 14px;
372 height: 14px;
373 border-radius: 50%;
374 display: inline-flex;
375 align-items: center;
376 justify-content: center;
377 font-size: 7px;
378 font-weight: var(--font-weight-bold);
379 color: #fff;
380 flex-shrink: 0;
381 }
382
383 .prl-date { color: var(--text-muted); flex-shrink: 0; }
384
385 .prl-snippet {
386 font-size: 11px;
387 color: var(--text-muted);
388 overflow: hidden;
389 white-space: nowrap;
390 text-overflow: ellipsis;
391 opacity: 0.75;
392 min-width: 0;
393 max-width: 320px;
394 }
395
396 // Row aside — merged label + SHA
397 .prl-row-aside {
398 display: flex;
399 flex-direction: row;
400 align-items: center;
401 gap: 8px;
402 flex-shrink: 0;
403 }
404
405 .prl-merged-label {
406 display: inline-flex;
407 align-items: center;
408 gap: 4px;
409 font-size: 11px;
410 color: $proposal-merged;
411 opacity: 0.8;
412 }
413
414 .prl-closed-label {
415 font-size: 11px;
416 color: $proposal-closed;
417 opacity: 0.7;
418 }
419
420 .prl-sha {
421 font-size: 10px;
422 font-family: var(--font-mono);
423 color: var(--text-muted);
424 opacity: 0.6;
425 text-decoration: none;
426 transition: opacity var(--transition-fast);
427 &:hover { opacity: 1; text-decoration: underline; }
428 }
429
430 // Chevron
431 .prl-chevron {
432 flex-shrink: 0;
433 color: var(--text-muted);
434 opacity: 0;
435 transition: opacity var(--transition-fast);
436 }
437 .prl-row:hover .prl-chevron { opacity: 0.5; }
438
439 // ── Empty state ────────────────────────────────────────────────────────────────
440 .prl-empty {
441 display: flex;
442 flex-direction: column;
443 align-items: center;
444 justify-content: center;
445 padding: var(--space-12) var(--space-6);
446 text-align: center;
447 gap: var(--space-3);
448 }
449
450 .prl-empty-icon {
451 opacity: 0.18;
452 margin-bottom: var(--space-2);
453 }
454
455 .prl-empty-title {
456 font-size: 18px;
457 font-weight: var(--font-weight-semibold);
458 color: var(--text-secondary);
459 }
460
461 .prl-empty-desc {
462 font-size: 13px;
463 color: var(--text-muted);
464 line-height: 1.6;
465 max-width: 380px;
466 }
467
468 .prl-empty-cli {
469 display: inline-flex;
470 align-items: center;
471 gap: 8px;
472 margin-top: var(--space-2);
473 padding: var(--space-2) var(--space-4);
474 border-radius: var(--radius-md);
475 background: var(--bg-overlay);
476 border: 1px solid var(--border-subtle);
477 font-size: 12px;
478 }
479
480 .prl-empty-cli-prompt {
481 font-family: var(--font-mono);
482 color: var(--text-muted);
483 opacity: 0.5;
484 }
485
486 .prl-empty-cli-cmd {
487 font-family: var(--font-mono);
488 color: var(--text-primary);
489 font-weight: var(--font-weight-medium);
490 }
491
492 .prl-empty-cli-hint {
493 color: var(--text-muted);
494 border-left: 1px solid var(--border-subtle);
495 padding-left: 8px;
496 }
497
498 // ── HTMX row fade-in ───────────────────────────────────────────────────────────
499 .prl-row {
500 animation: prl-row-in 180ms ease both;
501 }
502
503 @keyframes prl-row-in {
504 from { opacity: 0; transform: translateY(4px); }
505 to { opacity: 1; transform: translateY(0); }
506 }
507
508 // Stagger first 8 rows
509 @for $i from 1 through 8 {
510 .prl-row:nth-child(#{$i}) {
511 animation-delay: #{($i - 1) * 28}ms;
512 }
513 }
514
515 // ── Risk badge (Phase 2) ──────────────────────────────────────────────────────
516
517 .prl-risk-badge {
518 display: inline-flex;
519 align-items: center;
520 font-size: 0.62rem;
521 font-weight: 700;
522 text-transform: uppercase;
523 letter-spacing: 0.07em;
524 padding: 2px 7px;
525 border-radius: 9999px;
526 border: 1px solid;
527 font-family: var(--font-mono);
528 white-space: nowrap;
529
530 &--low {
531 color: #3fb950;
532 border-color: rgba(63,185,80,0.35);
533 background: rgba(63,185,80,0.08);
534 }
535 &--medium {
536 color: #d29922;
537 border-color: rgba(210,153,34,0.35);
538 background: rgba(210,153,34,0.08);
539 }
540 &--high {
541 color: #f0883e;
542 border-color: rgba(240,136,62,0.35);
543 background: rgba(240,136,62,0.08);
544 }
545 &--critical {
546 color: #ff2244;
547 border-color: rgba(255,34,68,0.35);
548 background: rgba(255,34,68,0.08);
549 }
550 }
File History 1 commit
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ 156 days ago