@principal-ai/subsystems-react 0.24.3 → 0.24.5
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/dist/components/session-events/SessionEventFeed.d.ts +2 -2
- package/dist/components/session-events/SessionEventFeed.js +9 -9
- package/dist/components/session-events/SessionEventFeed.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pierre/PierreSnippetView.d.ts.map +1 -1
- package/dist/pierre/PierreSnippetView.js +21 -1
- package/dist/pierre/PierreSnippetView.js.map +1 -1
- package/dist/pierre/scrollAnchor.d.ts.map +1 -1
- package/dist/pierre/scrollAnchor.js +9 -1
- package/dist/pierre/scrollAnchor.js.map +1 -1
- package/dist/subsystem/ComponentDeclaration.d.ts +5 -2
- package/dist/subsystem/ComponentDeclaration.d.ts.map +1 -1
- package/dist/subsystem/ComponentDeclaration.js +18 -3
- package/dist/subsystem/ComponentDeclaration.js.map +1 -1
- package/dist/subsystem/ConstructsCatalog.d.ts.map +1 -1
- package/dist/subsystem/ConstructsCatalog.js +32 -11
- package/dist/subsystem/ConstructsCatalog.js.map +1 -1
- package/dist/subsystem/IssueList.d.ts +4 -2
- package/dist/subsystem/IssueList.d.ts.map +1 -1
- package/dist/subsystem/IssueList.js +105 -31
- package/dist/subsystem/IssueList.js.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
- package/dist/subsystem/SubsystemComponentGraph.js +3 -1
- package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
- package/dist/subsystem/declarationRef.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/session-events/SessionEventFeed.tsx +9 -9
- package/src/index.ts +1 -0
- package/src/pierre/PierreSnippetView.tsx +25 -1
- package/src/pierre/scrollAnchor.ts +7 -1
- package/src/stories/Subsystem/ComponentGraph/Issues.stories.tsx +74 -5
- package/src/subsystem/ComponentDeclaration.tsx +30 -3
- package/src/subsystem/ConstructsCatalog.tsx +52 -28
- package/src/subsystem/IssueList.tsx +117 -31
- package/src/subsystem/SubsystemComponentGraph.tsx +5 -0
- package/src/subsystem/declarationRef.ts +1 -1
|
@@ -66,7 +66,7 @@ export interface ComponentVerificationState {
|
|
|
66
66
|
inlineParameters?: number;
|
|
67
67
|
};
|
|
68
68
|
declaration?: {
|
|
69
|
-
freshness: '
|
|
69
|
+
freshness: 'fresh' | 'stale' | 'missing' | 'unanchored' | 'unchecked';
|
|
70
70
|
ref?: {
|
|
71
71
|
startLine: number;
|
|
72
72
|
lineHash: string;
|
|
@@ -120,6 +120,9 @@ export interface ComponentDeclarationProps {
|
|
|
120
120
|
verification?: ComponentVerificationState | null;
|
|
121
121
|
/** Start with the file path row visible (catalog / source-first views). */
|
|
122
122
|
defaultShowFile?: boolean;
|
|
123
|
+
/** True while this component's file is open in the host drawer — keeps the
|
|
124
|
+
* declaration visibly tied to the source being read. */
|
|
125
|
+
fileOpen?: boolean;
|
|
123
126
|
}
|
|
124
127
|
|
|
125
128
|
function verificationSummary(
|
|
@@ -259,6 +262,7 @@ export function ComponentDeclaration({
|
|
|
259
262
|
onVerify,
|
|
260
263
|
verification,
|
|
261
264
|
defaultShowFile = false,
|
|
265
|
+
fileOpen = false,
|
|
262
266
|
}: ComponentDeclarationProps) {
|
|
263
267
|
const { theme, mode } = useTheme();
|
|
264
268
|
const pierreSyntaxTheme = resolvePierreSyntaxThemeName(mode);
|
|
@@ -380,8 +384,31 @@ export function ComponentDeclaration({
|
|
|
380
384
|
</button>
|
|
381
385
|
);
|
|
382
386
|
const verifyBusy = verification?.phase === 'checking';
|
|
387
|
+
const openPill = fileOpen ? (
|
|
388
|
+
<span
|
|
389
|
+
title="This declaration's file is open below"
|
|
390
|
+
style={{
|
|
391
|
+
display: 'inline-flex',
|
|
392
|
+
alignItems: 'center',
|
|
393
|
+
gap: 4,
|
|
394
|
+
height: 18,
|
|
395
|
+
padding: '0 6px',
|
|
396
|
+
border: `1px solid ${theme.colors.accent ?? color}`,
|
|
397
|
+
borderRadius: 999,
|
|
398
|
+
color: theme.colors.accent ?? color,
|
|
399
|
+
fontFamily: theme.fonts.monospace,
|
|
400
|
+
fontSize: theme.fontSizes[0] * 0.85,
|
|
401
|
+
letterSpacing: 0.4,
|
|
402
|
+
textTransform: 'uppercase',
|
|
403
|
+
whiteSpace: 'nowrap',
|
|
404
|
+
}}
|
|
405
|
+
>
|
|
406
|
+
file open
|
|
407
|
+
</span>
|
|
408
|
+
) : null;
|
|
383
409
|
const headerActions = (
|
|
384
|
-
<span style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap:
|
|
410
|
+
<span style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
411
|
+
{openPill}
|
|
385
412
|
{onVerify && (
|
|
386
413
|
<button
|
|
387
414
|
type="button"
|
|
@@ -458,7 +485,7 @@ export function ComponentDeclaration({
|
|
|
458
485
|
'purl',
|
|
459
486
|
),
|
|
460
487
|
);
|
|
461
|
-
} else if (onVerify) {
|
|
488
|
+
} else if (onVerify || fileOpen) {
|
|
462
489
|
lines.push(line(headerActions, 'actions'));
|
|
463
490
|
}
|
|
464
491
|
|
|
@@ -88,6 +88,7 @@ export function ConstructsCatalog({
|
|
|
88
88
|
const { theme, mode } = useTheme();
|
|
89
89
|
const pierreTheme = resolvePierreSyntaxThemeName(mode);
|
|
90
90
|
const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
|
|
91
|
+
const accentColor = theme.colors.accent ?? theme.colors.info;
|
|
91
92
|
const [visibleIds, setVisibleIds] = useState<string[]>(() =>
|
|
92
93
|
components[0] ? [components[0].id] : [],
|
|
93
94
|
);
|
|
@@ -121,6 +122,20 @@ export function ConstructsCatalog({
|
|
|
121
122
|
?.scrollIntoView({ block: 'nearest' });
|
|
122
123
|
}, [visibleIds]);
|
|
123
124
|
|
|
125
|
+
// Keep the declaration whose file is open in view, so the source and its
|
|
126
|
+
// signature stay legible together.
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
if (!drawer) return;
|
|
129
|
+
const match =
|
|
130
|
+
components.find(
|
|
131
|
+
(c) => c.file === drawer.file && c.declarationRef?.startLine === drawer.startLine,
|
|
132
|
+
) ?? components.find((c) => c.file === drawer.file);
|
|
133
|
+
if (!match) return;
|
|
134
|
+
document
|
|
135
|
+
.getElementById(`construct-signature-${match.id}`)
|
|
136
|
+
?.scrollIntoView({ block: 'nearest' });
|
|
137
|
+
}, [components, drawer]);
|
|
138
|
+
|
|
124
139
|
// Drop ids that left the model; if nothing remains, show the first construct.
|
|
125
140
|
useEffect(() => {
|
|
126
141
|
const ids = new Set(components.map((c) => c.id));
|
|
@@ -423,6 +438,7 @@ export function ConstructsCatalog({
|
|
|
423
438
|
);
|
|
424
439
|
const role = rightBadgeLabel(c);
|
|
425
440
|
const roleColor = rightBadgeColor(c);
|
|
441
|
+
const rowOpen = drawer != null && !!c.file && c.file === drawer.file;
|
|
426
442
|
return (
|
|
427
443
|
<li key={c.id} role="presentation">
|
|
428
444
|
<button
|
|
@@ -447,9 +463,12 @@ export function ConstructsCatalog({
|
|
|
447
463
|
? theme.colors.background
|
|
448
464
|
: 'transparent',
|
|
449
465
|
cursor: 'pointer',
|
|
450
|
-
boxShadow:
|
|
451
|
-
? `inset 0 0 0 1px ${theme.colors.border}`
|
|
452
|
-
:
|
|
466
|
+
boxShadow: [
|
|
467
|
+
visible ? `inset 0 0 0 1px ${theme.colors.border}` : null,
|
|
468
|
+
rowOpen ? `inset 2px 0 0 ${accentColor}` : null,
|
|
469
|
+
]
|
|
470
|
+
.filter(Boolean)
|
|
471
|
+
.join(', ') || undefined,
|
|
453
472
|
outline: focused && !visible ? `1px dotted ${muted}` : undefined,
|
|
454
473
|
outlineOffset: -1,
|
|
455
474
|
opacity: visible ? 1 : 0.72,
|
|
@@ -547,31 +566,36 @@ export function ConstructsCatalog({
|
|
|
547
566
|
}}
|
|
548
567
|
>
|
|
549
568
|
{visibleComponents.length > 0 ? (
|
|
550
|
-
visibleComponents.map((c) =>
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
569
|
+
visibleComponents.map((c) => {
|
|
570
|
+
const open = drawer != null && !!c.file && c.file === drawer.file;
|
|
571
|
+
return (
|
|
572
|
+
<div
|
|
573
|
+
key={c.id}
|
|
574
|
+
id={`construct-signature-${c.id}`}
|
|
575
|
+
style={{
|
|
576
|
+
border: `1px solid ${open ? accentColor : theme.colors.border}`,
|
|
577
|
+
boxShadow: open ? `0 0 0 1px ${accentColor}` : undefined,
|
|
578
|
+
borderRadius: 8,
|
|
579
|
+
overflow: 'hidden',
|
|
580
|
+
flexShrink: 0,
|
|
581
|
+
}}
|
|
582
|
+
>
|
|
583
|
+
<ComponentDeclaration
|
|
584
|
+
component={c}
|
|
585
|
+
onOpenFile={fileViewer ? onOpenFile : undefined}
|
|
586
|
+
defaultShowFile={!!fileViewer}
|
|
587
|
+
onRelatedSelect={onRelatedSelect}
|
|
588
|
+
onVerify={onVerifyComponent}
|
|
589
|
+
fileOpen={open}
|
|
590
|
+
verification={
|
|
591
|
+
componentVerification && focusedId === c.id
|
|
592
|
+
? componentVerification
|
|
593
|
+
: undefined
|
|
594
|
+
}
|
|
595
|
+
/>
|
|
596
|
+
</div>
|
|
597
|
+
);
|
|
598
|
+
})
|
|
575
599
|
) : (
|
|
576
600
|
<p
|
|
577
601
|
style={{
|
|
@@ -27,6 +27,7 @@ export type SubsystemIssueTargetKind =
|
|
|
27
27
|
| 'relation'
|
|
28
28
|
| 'module'
|
|
29
29
|
| 'walkthrough'
|
|
30
|
+
| 'repo'
|
|
30
31
|
| 'graph';
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -34,6 +35,7 @@ export type SubsystemIssueTargetKind =
|
|
|
34
35
|
* constructs → static topology → runtime topology → walkthrough.
|
|
35
36
|
*/
|
|
36
37
|
export type SubsystemIssueCategory =
|
|
38
|
+
| 'repo'
|
|
37
39
|
| 'construct'
|
|
38
40
|
| 'static-topology'
|
|
39
41
|
| 'runtime-topology'
|
|
@@ -41,6 +43,7 @@ export type SubsystemIssueCategory =
|
|
|
41
43
|
|
|
42
44
|
/** Layer order + display names, shared by the list and its headers. */
|
|
43
45
|
export const SUBSYSTEM_ISSUE_CATEGORIES: SubsystemIssueCategory[] = [
|
|
46
|
+
'repo',
|
|
44
47
|
'construct',
|
|
45
48
|
'static-topology',
|
|
46
49
|
'runtime-topology',
|
|
@@ -51,6 +54,7 @@ export const SUBSYSTEM_ISSUE_CATEGORY_LABEL: Record<
|
|
|
51
54
|
SubsystemIssueCategory,
|
|
52
55
|
string
|
|
53
56
|
> = {
|
|
57
|
+
repo: 'Repositories',
|
|
54
58
|
construct: 'Constructs',
|
|
55
59
|
'static-topology': 'Static topology',
|
|
56
60
|
'runtime-topology': 'Runtime topology',
|
|
@@ -60,18 +64,18 @@ export const SUBSYSTEM_ISSUE_CATEGORY_LABEL: Record<
|
|
|
60
64
|
/** Default `kind` → layer. `boundary_*` splits by module (static) vs process (runtime). */
|
|
61
65
|
const KIND_CATEGORY: Record<string, SubsystemIssueCategory> = {
|
|
62
66
|
missing_file: 'construct',
|
|
63
|
-
|
|
67
|
+
symbol_ambiguous: 'construct',
|
|
68
|
+
symbol_unmatched: 'construct',
|
|
64
69
|
stale_declaration: 'construct',
|
|
65
70
|
construct_mismatch: 'construct',
|
|
66
71
|
construct_unconfirmed: 'construct',
|
|
67
72
|
signature_mismatch: 'construct',
|
|
68
73
|
signature_unconfirmed: 'construct',
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
repo_unresolved: 'repo',
|
|
75
|
+
graphify_unavailable: 'repo',
|
|
71
76
|
topology_broken_endpoint: 'static-topology',
|
|
72
77
|
topology_import_unconfirmed: 'static-topology',
|
|
73
78
|
topology_relation_unconfirmed: 'static-topology',
|
|
74
|
-
boundary_module_without_file: 'static-topology',
|
|
75
79
|
boundary_module_file_mismatch: 'static-topology',
|
|
76
80
|
boundary_process_nest_disagree: 'runtime-topology',
|
|
77
81
|
walkthrough: 'walkthrough',
|
|
@@ -124,27 +128,28 @@ export function humanizeIssueKind(kind: string): string {
|
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
/**
|
|
127
|
-
* Curated
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
+
* Curated labels. Construct-layer findings stay fully qualified ("Construct
|
|
132
|
+
* declaration file missing", "Construct type mismatch") rather than relying on
|
|
133
|
+
* the category header — this UI is new and the extra words read clearer.
|
|
134
|
+
* Topology findings drop the `topology_`/`boundary_` prefix since the layer
|
|
135
|
+
* already scopes them. Explicit `issue.kindLabel` wins.
|
|
131
136
|
*/
|
|
132
137
|
const KIND_LABEL: Record<string, string> = {
|
|
133
|
-
missing_file: '
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
138
|
+
missing_file: 'Construct declaration file missing',
|
|
139
|
+
symbol_ambiguous: 'Multiple construct symbol matches',
|
|
140
|
+
symbol_unmatched: 'Construct symbol unconfirmed',
|
|
141
|
+
stale_declaration: 'Construct declaration drift',
|
|
142
|
+
construct_mismatch: 'Construct type mismatch',
|
|
143
|
+
construct_unconfirmed: 'Construct type unconfirmed',
|
|
144
|
+
signature_mismatch: 'Construct signature mismatch',
|
|
145
|
+
signature_unconfirmed: 'Construct signature unconfirmed',
|
|
146
|
+
repo_unresolved: 'No repository clone',
|
|
147
|
+
graphify_unavailable: 'Graphify cache unavailable',
|
|
148
|
+
topology_broken_endpoint: 'Construct relationship broken',
|
|
143
149
|
topology_import_unconfirmed: 'Import unconfirmed',
|
|
144
|
-
topology_relation_unconfirmed: '
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
boundary_process_nest_disagree: 'Process nest disagree',
|
|
150
|
+
topology_relation_unconfirmed: 'Relationship unconfirmed',
|
|
151
|
+
boundary_module_file_mismatch: 'Declaration file outside module',
|
|
152
|
+
boundary_process_nest_disagree: 'Module spans multiple process contexts',
|
|
148
153
|
walkthrough: 'Step issue',
|
|
149
154
|
};
|
|
150
155
|
|
|
@@ -153,6 +158,44 @@ export function issueKindLabel(issue: SubsystemIssue): string {
|
|
|
153
158
|
return issue.kindLabel ?? KIND_LABEL[issue.kind] ?? humanizeIssueKind(issue.kind);
|
|
154
159
|
}
|
|
155
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Display order within the list, by verification pipeline — not severity.
|
|
163
|
+
* Mirrors the per-component check order (file → symbol → declaration → type →
|
|
164
|
+
* signature), then topology (integrity → corroboration → membership) and the
|
|
165
|
+
* remaining layers. Within a stage, "unconfirmed" precedes "mismatch": you
|
|
166
|
+
* reach a verdict before you can find it wrong.
|
|
167
|
+
*/
|
|
168
|
+
const KIND_ORDER: Record<string, number> = {
|
|
169
|
+
// Repositories — availability precondition
|
|
170
|
+
repo_unresolved: 0,
|
|
171
|
+
graphify_unavailable: 1,
|
|
172
|
+
// Constructs — file → symbol → declaration → type → signature
|
|
173
|
+
missing_file: 10,
|
|
174
|
+
symbol_unmatched: 11,
|
|
175
|
+
symbol_ambiguous: 12,
|
|
176
|
+
stale_declaration: 13,
|
|
177
|
+
construct_unconfirmed: 14,
|
|
178
|
+
construct_mismatch: 15,
|
|
179
|
+
signature_unconfirmed: 16,
|
|
180
|
+
signature_mismatch: 17,
|
|
181
|
+
// Static topology — edge integrity → corroboration → membership
|
|
182
|
+
topology_broken_endpoint: 20,
|
|
183
|
+
topology_relation_unconfirmed: 21,
|
|
184
|
+
topology_import_unconfirmed: 22,
|
|
185
|
+
boundary_module_file_mismatch: 23,
|
|
186
|
+
// Runtime topology
|
|
187
|
+
boundary_process_nest_disagree: 30,
|
|
188
|
+
// Walkthrough
|
|
189
|
+
walkthrough: 40,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const KIND_ORDER_FALLBACK = 100;
|
|
193
|
+
|
|
194
|
+
/** Sort key for a kind; unknown kinds sort last. */
|
|
195
|
+
export function issueKindOrder(kind: string): number {
|
|
196
|
+
return KIND_ORDER[kind] ?? KIND_ORDER_FALLBACK;
|
|
197
|
+
}
|
|
198
|
+
|
|
156
199
|
export function severityRank(severity: SubsystemIssueSeverity): number {
|
|
157
200
|
return SEVERITY_RANK[severity] ?? SEVERITY_RANK.info;
|
|
158
201
|
}
|
|
@@ -246,7 +289,12 @@ export function groupIssuesByCategory(
|
|
|
246
289
|
}
|
|
247
290
|
return SUBSYSTEM_ISSUE_CATEGORIES.map((category) => {
|
|
248
291
|
const grouped = byCategory.get(category) ?? [];
|
|
249
|
-
|
|
292
|
+
// Logical pipeline order, then by target label (stable for the rest).
|
|
293
|
+
grouped.sort((a, b) => {
|
|
294
|
+
const byKind = issueKindOrder(a.kind) - issueKindOrder(b.kind);
|
|
295
|
+
if (byKind !== 0) return byKind;
|
|
296
|
+
return (a.target?.label ?? '').localeCompare(b.target?.label ?? '');
|
|
297
|
+
});
|
|
250
298
|
return {
|
|
251
299
|
category,
|
|
252
300
|
label: SUBSYSTEM_ISSUE_CATEGORY_LABEL[category],
|
|
@@ -269,9 +317,10 @@ function severityColor(
|
|
|
269
317
|
|
|
270
318
|
const TARGET_KIND_LABEL: Record<SubsystemIssueTargetKind, string> = {
|
|
271
319
|
component: 'component',
|
|
272
|
-
relation: '
|
|
320
|
+
relation: 'relationship',
|
|
273
321
|
module: 'module',
|
|
274
322
|
walkthrough: 'flow',
|
|
323
|
+
repo: 'repo',
|
|
275
324
|
graph: 'model',
|
|
276
325
|
};
|
|
277
326
|
|
|
@@ -445,6 +494,19 @@ export function SubsystemIssueList({
|
|
|
445
494
|
const { theme } = useTheme();
|
|
446
495
|
const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
|
|
447
496
|
const categories = groupIssuesByCategory(issues);
|
|
497
|
+
// Collapsed categories (by id). Everything starts expanded.
|
|
498
|
+
const [collapsed, setCollapsed] = useState<Set<SubsystemIssueCategory>>(
|
|
499
|
+
() => new Set(),
|
|
500
|
+
);
|
|
501
|
+
const [hovered, setHovered] = useState<SubsystemIssueCategory | null>(null);
|
|
502
|
+
const toggleCollapsed = (category: SubsystemIssueCategory) => {
|
|
503
|
+
setCollapsed((prev) => {
|
|
504
|
+
const next = new Set(prev);
|
|
505
|
+
if (next.has(category)) next.delete(category);
|
|
506
|
+
else next.add(category);
|
|
507
|
+
return next;
|
|
508
|
+
});
|
|
509
|
+
};
|
|
448
510
|
|
|
449
511
|
return (
|
|
450
512
|
<div style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
|
|
@@ -455,19 +517,39 @@ export function SubsystemIssueList({
|
|
|
455
517
|
const accent = category.severity
|
|
456
518
|
? severityColor(category.severity, theme.colors, muted)
|
|
457
519
|
: theme.colors.success;
|
|
520
|
+
const isCollapsed = collapsed.has(category.category);
|
|
521
|
+
const isHovered = hovered === category.category;
|
|
458
522
|
return (
|
|
459
523
|
<div key={category.category}>
|
|
460
|
-
<
|
|
524
|
+
<button
|
|
525
|
+
type="button"
|
|
526
|
+
aria-expanded={!isCollapsed}
|
|
527
|
+
onClick={() => toggleCollapsed(category.category)}
|
|
528
|
+
onMouseEnter={() => setHovered(category.category)}
|
|
529
|
+
onMouseLeave={() => setHovered(null)}
|
|
461
530
|
style={{
|
|
462
531
|
position: 'sticky',
|
|
463
532
|
top: 0,
|
|
464
533
|
zIndex: 1,
|
|
534
|
+
width: '100%',
|
|
535
|
+
boxSizing: 'border-box',
|
|
465
536
|
display: 'flex',
|
|
466
537
|
alignItems: 'center',
|
|
467
|
-
gap:
|
|
468
|
-
padding: '
|
|
469
|
-
background:
|
|
538
|
+
gap: 8,
|
|
539
|
+
padding: '9px 12px',
|
|
540
|
+
background: isHovered
|
|
541
|
+
? (theme.colors.backgroundHover ??
|
|
542
|
+
theme.colors.backgroundSecondary ??
|
|
543
|
+
theme.colors.background)
|
|
544
|
+
: (theme.colors.backgroundTertiary ??
|
|
545
|
+
theme.colors.backgroundSecondary ??
|
|
546
|
+
theme.colors.background),
|
|
547
|
+
border: 'none',
|
|
548
|
+
borderTop: `1px solid ${theme.colors.border}`,
|
|
470
549
|
borderBottom: `1px solid ${theme.colors.border}`,
|
|
550
|
+
cursor: 'pointer',
|
|
551
|
+
textAlign: 'left',
|
|
552
|
+
fontFamily: theme.fonts.body,
|
|
471
553
|
}}
|
|
472
554
|
>
|
|
473
555
|
<span
|
|
@@ -475,9 +557,9 @@ export function SubsystemIssueList({
|
|
|
475
557
|
flex: 1,
|
|
476
558
|
minWidth: 0,
|
|
477
559
|
fontSize: theme.fontSizes[1],
|
|
478
|
-
fontWeight:
|
|
560
|
+
fontWeight: 700,
|
|
561
|
+
letterSpacing: 0.2,
|
|
479
562
|
color: clean ? muted : theme.colors.text,
|
|
480
|
-
fontFamily: theme.fonts.body,
|
|
481
563
|
whiteSpace: 'nowrap',
|
|
482
564
|
overflow: 'hidden',
|
|
483
565
|
textOverflow: 'ellipsis',
|
|
@@ -500,8 +582,12 @@ export function SubsystemIssueList({
|
|
|
500
582
|
{category.count}
|
|
501
583
|
</span>
|
|
502
584
|
)}
|
|
503
|
-
|
|
585
|
+
<span style={{ display: 'inline-flex', color: muted, flexShrink: 0 }}>
|
|
586
|
+
{isCollapsed ? <ChevronRight size={14} /> : <ChevronDown size={14} />}
|
|
587
|
+
</span>
|
|
588
|
+
</button>
|
|
504
589
|
{!clean &&
|
|
590
|
+
!isCollapsed &&
|
|
505
591
|
category.issues.map((issue) => (
|
|
506
592
|
<SubsystemIssueCard
|
|
507
593
|
key={issue.id}
|
|
@@ -1993,6 +1993,11 @@ function Inner({ components, relations, walkthroughs, onSelect, onEdgeSelect, me
|
|
|
1993
1993
|
onRelatedSelect={resolveRelatedComponent}
|
|
1994
1994
|
onVerify={onVerifyComponent}
|
|
1995
1995
|
verification={componentVerification}
|
|
1996
|
+
fileOpen={
|
|
1997
|
+
drawerTarget?.kind === 'file' &&
|
|
1998
|
+
!!selected.file &&
|
|
1999
|
+
selected.file === drawerTarget.file
|
|
2000
|
+
}
|
|
1996
2001
|
/>
|
|
1997
2002
|
</div>
|
|
1998
2003
|
)}
|