gabriel / musehub public
_symbol-view.scss
601 lines 11.3 KB
Raw
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ breaking 156 days ago
1 // _symbol-view.scss — Symbol dependency graph view (.sv-* prefix)
2
3 // ── Code domain symbol-graph view (view.html + view.ts) ─────────────────────
4 //
5 // Two-column layout: left = commit navigator + semantic changes panel,
6 // right = D3 symbol graph SVG + info panel.
7 //
8 // BEM-ish class prefix: .sv- (symbol-view)
9
10 .sv-layout {
11 display: grid;
12 grid-template-columns: 280px 1fr;
13 gap: var(--space-4, 16px);
14 min-height: 560px;
15 align-items: start;
16
17 @media (max-width: 860px) {
18 grid-template-columns: 1fr;
19 }
20 }
21
22 // ── Left column ──────────────────────────────────────────────────────────────
23
24 .sv-left {
25 display: flex;
26 flex-direction: column;
27 gap: var(--space-3, 12px);
28 min-width: 0;
29 }
30
31 .sv-panel {
32 background: var(--bg-secondary, #161b22);
33 border: 1px solid var(--border-color, #30363d);
34 border-radius: 8px;
35 overflow: hidden;
36 }
37
38 .sv-panel-hd {
39 display: flex;
40 align-items: center;
41 justify-content: space-between;
42 padding: 10px 14px;
43 border-bottom: 1px solid var(--border-color, #30363d);
44 background: var(--bg-tertiary, #0d1117);
45 }
46
47 .sv-panel-title {
48 font-size: 12px;
49 font-weight: 600;
50 color: var(--text-primary, #e6edf3);
51 text-transform: uppercase;
52 letter-spacing: .05em;
53 }
54
55 .sv-sym-count {
56 font-size: 11px;
57 color: var(--text-muted, #7d8590);
58 font-family: var(--font-mono);
59 }
60
61 // Commit navigator
62
63 .sv-nav-btns {
64 display: flex;
65 gap: 4px;
66 }
67
68 .sv-nav-btn {
69 display: flex;
70 align-items: center;
71 justify-content: center;
72 width: 24px;
73 height: 24px;
74 padding: 0;
75 border: 1px solid var(--border-color, #30363d);
76 border-radius: 4px;
77 background: transparent;
78 color: var(--text-muted, #7d8590);
79 cursor: pointer;
80 transition: border-color .15s, color .15s;
81
82 &:hover {
83 border-color: var(--color-accent, #4493f8);
84 color: var(--color-accent, #4493f8);
85 }
86
87 &:active { opacity: .7; }
88 }
89
90 .sv-commit-list {
91 list-style: none;
92 margin: 0;
93 padding: 4px 0;
94 max-height: 260px;
95 overflow-y: auto;
96 }
97
98 .sv-commit-item {
99 display: flex;
100 flex-direction: column;
101 gap: 2px;
102 padding: 8px 14px;
103 cursor: pointer;
104 border-left: 2px solid transparent;
105 transition: background .12s, border-color .12s;
106
107 &:hover {
108 background: var(--bg-hover, rgba(177,186,196,.08));
109 }
110
111 &:focus-visible {
112 outline: 2px solid var(--color-accent, #4493f8);
113 outline-offset: -2px;
114 }
115 }
116
117 .sv-commit-active {
118 border-left-color: var(--color-accent, #4493f8);
119 background: var(--bg-hover, rgba(177,186,196,.06));
120 }
121
122 .sv-commit-sha {
123 font-family: var(--font-mono);
124 font-size: 10px;
125 color: var(--color-accent, #4493f8);
126 }
127
128 .sv-commit-msg {
129 font-size: 12px;
130 color: var(--text-primary, #e6edf3);
131 white-space: nowrap;
132 overflow: hidden;
133 text-overflow: ellipsis;
134 }
135
136 .sv-commit-meta {
137 display: flex;
138 gap: 6px;
139 align-items: center;
140 }
141
142 .sv-commit-branch {
143 font-size: 10px;
144 font-family: var(--font-mono);
145 color: var(--text-muted, #7d8590);
146 background: var(--bg-hover, rgba(177,186,196,.08));
147 padding: 1px 5px;
148 border-radius: 3px;
149 }
150
151 .sv-commit-ts {
152 font-size: 10px;
153 color: var(--text-muted, #7d8590);
154 }
155
156 .sv-commit-placeholder,
157 .sv-commit-empty {
158 padding: 12px 14px;
159 font-size: 12px;
160 color: var(--text-muted, #7d8590);
161 }
162
163 // Semantic Changes panel
164
165 .sv-analyze {
166 flex: 1;
167 }
168
169 .sv-analyze-body {
170 padding: 10px 14px;
171 max-height: 380px;
172 overflow-y: auto;
173 }
174
175 .sv-analyze-msg {
176 font-size: 12px;
177 color: var(--text-secondary, #8b949e);
178 margin: 0 0 10px;
179 line-height: 1.5;
180 font-style: italic;
181 }
182
183 .sv-analyze-empty {
184 font-size: 12px;
185 color: var(--text-muted, #7d8590);
186 margin: 0;
187 }
188
189 .sv-file-card {
190 margin-bottom: 12px;
191 }
192
193 .sv-file-hd {
194 display: flex;
195 align-items: center;
196 gap: 6px;
197 margin-bottom: 4px;
198 }
199
200 .sv-file-path {
201 font-family: var(--font-mono);
202 font-size: 11px;
203 color: var(--text-primary, #e6edf3);
204 flex: 1;
205 white-space: nowrap;
206 overflow: hidden;
207 text-overflow: ellipsis;
208 }
209
210 .sv-ext {
211 font-family: var(--font-mono);
212 font-size: 10px;
213 color: var(--text-muted, #7d8590);
214 background: var(--bg-hover, rgba(177,186,196,.08));
215 padding: 1px 4px;
216 border-radius: 3px;
217 }
218
219 .sv-file-sym-count {
220 font-size: 10px;
221 color: var(--text-muted, #7d8590);
222 white-space: nowrap;
223 }
224
225 .sv-sym-tree {
226 padding-left: 8px;
227 border-left: 1px solid var(--border-color, #30363d);
228 display: flex;
229 flex-direction: column;
230 gap: 2px;
231 }
232
233 .sv-sym-row {
234 display: flex;
235 align-items: center;
236 gap: 4px;
237 padding: 1px 0;
238 }
239
240 .sv-sym-indent {
241 font-size: 10px;
242 color: var(--text-muted, #7d8590);
243 margin-left: 8px;
244 }
245
246 .sv-sym-name {
247 font-family: var(--font-mono);
248 font-size: 11px;
249 color: var(--text-primary, #e6edf3);
250 flex: 1;
251 white-space: nowrap;
252 overflow: hidden;
253 text-overflow: ellipsis;
254 }
255
256 .sv-kind-chip {
257 font-size: 9px;
258 font-family: var(--font-mono);
259 padding: 1px 5px;
260 border-radius: 3px;
261 border: 1px solid;
262 white-space: nowrap;
263 }
264
265 // Op indicator dots
266
267 .sv-op-dot {
268 width: 7px;
269 height: 7px;
270 border-radius: 50%;
271 flex-shrink: 0;
272 }
273
274 .sv-op-dot-sm {
275 width: 5px;
276 height: 5px;
277 }
278
279 .sv-op-add { background: #34d399; }
280 .sv-op-del { background: #f87171; }
281 .sv-op-mod { background: #fbbf24; }
282
283 // ── Right column ─────────────────────────────────────────────────────────────
284
285 .sv-right {
286 display: flex;
287 flex-direction: column;
288 gap: var(--space-3, 12px);
289 min-width: 0;
290 }
291
292 .sv-graph-hd {
293 display: flex;
294 flex-direction: column;
295 gap: 8px;
296 }
297
298 .sv-stats {
299 font-size: 12px;
300 color: var(--text-muted, #7d8590);
301 font-family: var(--font-mono);
302 min-height: 18px;
303 }
304
305 .sv-controls-row {
306 display: flex;
307 align-items: center;
308 gap: 10px;
309 flex-wrap: wrap;
310 }
311
312 .sv-mode-btns {
313 display: flex;
314 gap: 2px;
315 }
316
317 .sv-mode-btn {
318 padding: 4px 12px;
319 font-size: 11px;
320 font-weight: 500;
321 border: 1px solid var(--border-color, #30363d);
322 border-radius: 6px;
323 background: transparent;
324 color: var(--text-muted, #7d8590);
325 cursor: pointer;
326 transition: background .12s, border-color .12s, color .12s;
327
328 &:first-child { border-radius: 6px 0 0 6px; }
329 &:last-child { border-radius: 0 6px 6px 0; }
330 &:not(:first-child):not(:last-child) { border-radius: 0; margin-left: -1px; }
331
332 &:hover {
333 background: var(--bg-hover, rgba(177,186,196,.08));
334 color: var(--text-primary, #e6edf3);
335 }
336 }
337
338 .sv-mode-active {
339 background: rgba(68, 147, 248, .12) !important;
340 border-color: var(--color-accent, #4493f8) !important;
341 color: var(--color-accent, #4493f8) !important;
342 }
343
344 .sv-mode-active-red {
345 background: rgba(248, 113, 113, .12) !important;
346 border-color: #f87171 !important;
347 color: #f87171 !important;
348 }
349
350 .sv-search-row {
351 display: flex;
352 gap: 6px;
353 flex: 1;
354 min-width: 0;
355 }
356
357 .sv-search {
358 flex: 1;
359 min-width: 0;
360 padding: 5px 10px;
361 font-size: 12px;
362 border: 1px solid var(--border-color, #30363d);
363 border-radius: 6px;
364 background: var(--bg-secondary, #161b22);
365 color: var(--text-primary, #e6edf3);
366 font-family: var(--font-mono);
367
368 &::placeholder { color: var(--text-muted, #7d8590); }
369 &:focus { outline: 2px solid var(--color-accent, #4493f8); outline-offset: -1px; border-color: transparent; }
370 }
371
372 .sv-kind-filter {
373 padding: 5px 8px;
374 font-size: 12px;
375 border: 1px solid var(--border-color, #30363d);
376 border-radius: 6px;
377 background: var(--bg-secondary, #161b22);
378 color: var(--text-primary, #e6edf3);
379 cursor: pointer;
380 }
381
382 // Graph SVG wrapper
383
384 .sv-graph-wrap {
385 position: relative;
386 background: var(--bg-secondary, #161b22);
387 border: 1px solid var(--border-color, #30363d);
388 border-radius: 8px;
389 overflow: hidden;
390 min-height: 320px;
391 }
392
393 .sv-sym-svg {
394 display: block;
395 width: 100%;
396 }
397
398 // D3 graph node states
399
400 .sg-node { cursor: pointer; }
401
402 .sg-node.sg-inactive {
403 opacity: .07;
404 pointer-events: none;
405 }
406
407 .sg-node.sg-filtered {
408 opacity: .08;
409 pointer-events: none;
410 }
411
412 .sg-node.sg-selected .sg-ring {
413 stroke-opacity: 1 !important;
414 stroke-width: 2.5 !important;
415 }
416
417 .sg-edge.inactive { opacity: .04; }
418
419 .sv-empty {
420 position: absolute;
421 inset: 0;
422 display: flex;
423 flex-direction: column;
424 align-items: center;
425 justify-content: center;
426 gap: 8px;
427 color: var(--text-muted, #7d8590);
428 pointer-events: none;
429 }
430
431 .sv-empty p { margin: 0; font-size: 13px; }
432 .sv-empty-sub { font-size: 11px !important; opacity: .7; }
433
434 // Symbol info panel
435
436 .sv-info-panel {
437 position: relative;
438 background: var(--bg-secondary, #161b22);
439 border: 1px solid var(--border-color, #30363d);
440 border-radius: 8px;
441 padding: 14px;
442 }
443
444 .sv-info-hd {
445 display: flex;
446 align-items: center;
447 gap: 8px;
448 margin-bottom: 10px;
449 padding-right: 24px;
450 }
451
452 .sv-info-name {
453 font-family: var(--font-mono);
454 font-size: 13px;
455 color: var(--color-accent, #4493f8);
456 flex: 1;
457 word-break: break-all;
458 }
459
460 .sv-info-kind-badge {
461 font-size: 10px;
462 font-family: var(--font-mono);
463 padding: 2px 7px;
464 border-radius: 4px;
465 border: 1px solid color-mix(in srgb, var(--kind-color, #78909c) 30%, transparent);
466 color: var(--kind-color, #78909c);
467 background: color-mix(in srgb, var(--kind-color, #78909c) 10%, transparent);
468 white-space: nowrap;
469 }
470
471 .sv-info-close {
472 position: absolute;
473 top: 12px;
474 right: 12px;
475 width: 20px;
476 height: 20px;
477 display: flex;
478 align-items: center;
479 justify-content: center;
480 border: none;
481 background: transparent;
482 color: var(--text-muted, #7d8590);
483 cursor: pointer;
484 border-radius: 4px;
485 padding: 0;
486
487 &:hover { color: var(--text-primary, #e6edf3); background: var(--bg-hover, rgba(177,186,196,.08)); }
488 }
489
490 .sv-info-dl {
491 display: flex;
492 flex-direction: column;
493 gap: 4px;
494 margin: 0;
495 }
496
497 .sv-info-row {
498 display: flex;
499 gap: 8px;
500 align-items: flex-start;
501 font-size: 11px;
502
503 dt {
504 color: var(--text-muted, #7d8590);
505 white-space: nowrap;
506 min-width: 48px;
507 padding-top: 2px;
508 }
509
510 dd { margin: 0; }
511 }
512
513 .sv-info-mono {
514 font-family: var(--font-mono);
515 font-size: 11px;
516 color: var(--text-secondary, #8b949e);
517 word-break: break-all;
518 }
519
520 .sv-info-summary {
521 color: var(--text-muted, #7d8590);
522 line-height: 1.5;
523 }
524
525 .sv-info-dead {
526 color: #f87171;
527 }
528
529 .sv-info-no-edges {
530 color: var(--text-muted, #7d8590);
531 }
532
533 .sv-info-pills {
534 display: flex;
535 flex-wrap: wrap;
536 gap: 3px;
537 }
538
539 .sv-info-pill {
540 font-family: var(--font-mono);
541 font-size: 10px;
542 padding: 1px 6px;
543 border-radius: 3px;
544 border: 1px solid;
545 white-space: nowrap;
546 }
547
548
549 // ── Responsive ────────────────────────────────────────────────────────────────
550
551 @media (max-width: 768px) {
552 .sv-layout {
553 grid-template-columns: 1fr;
554 grid-template-rows: auto 1fr;
555 }
556
557 .sv-left-panel {
558 max-height: 280px;
559 overflow-y: auto;
560 }
561
562 .sv-graph-panel {
563 min-height: 320px;
564 }
565
566 .sv-commit-nav {
567 flex-direction: row;
568 overflow-x: auto;
569 gap: var(--space-2);
570 }
571
572 .sv-info-panel {
573 display: none;
574 }
575
576 .sv-controls {
577 flex-wrap: wrap;
578 gap: var(--space-1);
579 }
580 }
581
582 @media (max-width: 480px) {
583 .sv-layout {
584 min-height: 480px;
585 }
586
587 .sv-node-label {
588 font-size: 10px;
589 }
590
591 .sv-legend {
592 flex-wrap: wrap;
593 gap: var(--space-1);
594 font-size: 11px;
595 }
596
597 .sv-btn {
598 padding: 2px 8px;
599 font-size: 11px;
600 }
601 }
File History 1 commit
sha256:9590cee1e0ccd6c76528f005b95d634d80f5019f0dcb7c371e149adc31d1fb65 refactor: enforce gRPC framing on all MWP wire traffic Sonnet 4.6 minor ⚠ 156 days ago