-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFlowMap.module.css
More file actions
263 lines (243 loc) · 8.09 KB
/
Copy pathFlowMap.module.css
File metadata and controls
263 lines (243 loc) · 8.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
* FlowMap — React Flow (@xyflow/react v12) themed to the OtelContext dark token
* system. FlowMap.tsx imports React Flow's base stylesheet
* (@xyflow/react/dist/style.css); the rules here (a) theme React Flow's own DOM
* (background grid, panes, minimap, handles) to our --bg-inset instrument
* surface and (b) style the custom node/edge classes the component renders.
*
* Token-only colours (tokens.css). Token-driven motion is keyed off --dur-*,
* which the global prefers-reduced-motion block zeros. The ONE exception is
* React Flow's native edge animation (animated edges), which runs on the
* library's own keyframes — it gets an explicit prefers-reduced-motion guard at
* the bottom of this file.
*/
/* ---- the wrapper that holds the whole map ---- */
.container {
flex: 1;
position: relative;
min-height: 0;
min-width: 0;
border: 1px solid var(--stroke-1);
border-radius: var(--radius-2);
background: var(--bg-inset);
/* React Flow's <Background> draws the grid — no CSS background-image here. */
overflow: hidden;
}
/* ---- custom node: the token-themed status chip ---- */
/* Outline-led: the FULL status hue (passed inline as --node-color) carries the
* border; the fill is the opaque inset surface so edges + the grid pass BEHIND
* the chip and never bleed through the label. Reads as a status-coloured
* outline against the field. */
.chip {
display: flex;
align-items: center;
gap: 7px;
padding: 0 10px;
border: 1.5px solid var(--node-color);
border-radius: var(--radius-2);
background: var(--bg-inset);
font-size: var(--text-xs);
color: var(--text-1);
cursor: pointer;
box-sizing: border-box;
/* GPU transforms + border/shadow only — no SVG filter/blur. */
transition:
border-color var(--dur-2) var(--ease),
box-shadow var(--dur-2) var(--ease),
transform var(--dur-2) var(--ease);
}
/* Inspected node: accent ring + a small lift. The lift travels on --dur-2, so
* reduced motion (dur 0) preserves the static accent end-state. */
.selected {
border-color: var(--accent);
box-shadow: 0 0 0 1px var(--accent);
transform: scale(1.015);
transform-origin: center;
}
/* Field-wide focus-distortion: non-neighbour fade. */
.dimmed {
opacity: 0.5;
}
/* Blast-radius root (?impact=): same accent emphasis as the inspected node. */
.impactRoot {
border-color: var(--accent);
box-shadow: 0 0 0 1px var(--accent);
}
/* ---- level-of-detail: a status dot replaces the chip when zoomed out (dense
* 120-service view), so the 168px boxes stop occluding the routed edges. The
* dot is centred in the node box (dagre's edge waypoints still meet the box
* border) and carries the status hue. ---- */
.dotNode {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
cursor: pointer;
}
.dotNode::before {
content: '';
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--node-color);
box-shadow: 0 0 0 2px var(--bg-inset);
transition: box-shadow var(--dur-2) var(--ease);
}
/* Inspected / blast-root dot: accent ring, matching the chip's selected ring. */
.dotSelected::before {
box-shadow:
0 0 0 2px var(--bg-inset),
0 0 0 4px var(--accent);
}
/* Connection anchor, kept INVISIBLE. React Flow needs a source/target handle
* per node, but the floating edge computes the real border attachment point, so
* the handle dot itself must not show — otherwise edgeless nodes sprout a stray
* connector. opacity:0 keeps the element measured so edge routing still resolves
* its position; it never eats clicks. */
.handle {
width: 6px;
height: 6px;
min-width: 0;
min-height: 0;
border: 0;
background: transparent;
opacity: 0;
pointer-events: none;
}
/* Status dot — the same hue as the chip outline. */
.dot {
flex: none;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--node-color);
}
/* Service name — mono, truncates with an ellipsis when the chip is too narrow. */
.name {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-family: var(--font-mono);
color: var(--text-1);
}
/* Error-rate suffix — mono, tabular so digits line up across chips. */
.err {
flex: none;
font-family: var(--font-mono);
font-size: var(--text-2xs);
font-variant-numeric: tabular-nums;
color: var(--text-2);
}
/* ============================================================================
* React Flow base overrides (file-scope :global — these target React Flow's
* OWN DOM, which is a sibling of our chips, not nested under any module class).
* ==========================================================================*/
/* Let our --bg-inset container surface show through React Flow's root. */
:global(.react-flow) {
background: transparent;
}
/* Our .chip fully owns the node look — neutralise React Flow's node wrapper
* defaults (padding/border/background/radius) so they can't fight it. */
:global(.react-flow__node) {
padding: 0;
border: 0;
border-radius: 0;
background: transparent;
color: var(--text-1);
font-family: var(--font-sans);
}
/* Drop React Flow's default node focus box; keep a visible a11y ring on the
* chip via :focus-visible (nodes are focusable={true} in FlowMap.tsx). */
:global(.react-flow__node):focus,
:global(.react-flow__node):focus-visible {
outline: none;
box-shadow: none;
}
:global(.react-flow__node):focus-visible .chip {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* ---- grid: <Background variant="lines"> renders an SVG <pattern> of <path>s
* inside .react-flow__background. Colour those lines a subtle --stroke-1 (and
* set the lib's pattern-colour var as a belt-and-braces fallback). ---- */
.grid {
--xy-background-pattern-color: var(--stroke-1);
}
.grid :global(.react-flow__background-pattern path),
.grid :global(.react-flow__background-pattern) path {
stroke: var(--stroke-1);
stroke-width: 1;
}
/* ============================================================================
* React Flow Controls + MiniMap — themed to the dark token instrument surface
* so the map reads as a first-class graph tool, not the library's default
* white chrome. (file-scope :global — these target React Flow's own DOM.)
* ==========================================================================*/
/* Zoom / fit control cluster: a hairline token-themed stack, not a white box. */
.controls {
border: 1px solid var(--stroke-1);
border-radius: var(--radius-2);
overflow: hidden;
background: var(--bg-raised);
box-shadow: none;
}
.controls :global(.react-flow__controls-button) {
width: 28px;
height: 28px;
border: none;
border-bottom: 1px solid var(--stroke-1);
background: var(--bg-raised);
color: var(--text-2);
fill: var(--text-2);
transition:
background var(--dur-1) var(--ease),
color var(--dur-1) var(--ease);
}
.controls :global(.react-flow__controls-button):last-child {
border-bottom: none;
}
.controls :global(.react-flow__controls-button):hover {
background: var(--bg-overlay);
color: var(--text-1);
fill: var(--text-1);
}
.controls :global(.react-flow__controls-button svg) {
fill: currentColor;
}
/* Minimap: dark inset panel, hairline border; the out-of-view area dimmed by a
* token overlay; dots carry the same status hue as the chips. */
.minimap {
border: 1px solid var(--stroke-1);
border-radius: var(--radius-2);
background: var(--bg-inset);
overflow: hidden;
}
.minimap :global(.react-flow__minimap-mask) {
fill: var(--bg-inset);
opacity: 0.6;
}
/* Status fills override React Flow's base .react-flow__minimap-node fill. */
.miniCrit {
fill: var(--crit) !important;
}
.miniWarn {
fill: var(--warn) !important;
}
.miniOk {
fill: var(--ok) !important;
}
.miniUnknown {
fill: var(--unknown) !important;
}
/* React Flow's native animated edges run on the library's own keyframes (not a
* --dur token), so the global reduced-motion rule can't reach them. Stop the
* marching dashes for users who ask for reduced motion — leaving a static
* dashed edge and dropping the continuous edge-layer repaint for them. */
@media (prefers-reduced-motion: reduce) {
:global(.react-flow__edge.animated path) {
animation: none;
}
}