File size: 3,865 Bytes
fc01079
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/*
 * React Flow's default style.css ships opinionated defaults for the
 * `.react-flow__node-group` selector β€” fixed width (150px), inner padding,
 * a translucent grey fill, a 1px solid border and a 3px radius. They
 * conflict with our hierarchical layout where Dagre already sizes and
 * positions the group container; the actual visual (border + label) is
 * drawn by our own `GroupNode` React component inside the wrapper.
 *
 * IMPORTANT: do NOT override width/height here β€” React Flow sets them
 * inline from the node `style` (which we compute in `layoutGraph`). We
 * only neutralise the cosmetic defaults so our inner `Box` is the only
 * thing the user actually sees.
 */
.react-flow__node-group {
  background-color: transparent !important;
  background: transparent !important;
  border: none !important;
  border-radius: 0 !important;
  padding: 0 !important;
  /* Groups are visual containers, not interaction targets. Edges and
   * children must remain clickable. */
  pointer-events: none !important;
}

.react-flow__node-group.selectable:hover,
.react-flow__node-group.selectable.selected,
.react-flow__node-group.selectable:focus,
.react-flow__node-group.selectable:focus-visible {
  box-shadow: none !important;
}

/* ──────────────────────────────────────────────────────────────────────────
 * Granularity transitions
 *
 * When the user drags the granularity slider, React Flow rebuilds the
 * scene with new node positions and (sometimes) new node identities. We
 * use three coordinated CSS effects to make the change feel smooth:
 *
 *  1. `transition: transform` on every node so any node that survives the
 *     re-layout (stable id) glides to its new spot instead of teleporting.
 *  2. `transition` on `width`/`height` so group containers grow/shrink
 *     fluidly when they collapse a layer's interior or reveal it.
 *  3. A short `nodeFadeIn` keyframe on mount so newly created nodes (the
 *     children that "explode" out of a cluster, or the cluster that
 *     replaces them on the way up) fade in instead of popping.
 *
 * Edges can't tween their SVG `d` attribute reliably, so we just fade
 * them in on mount via `edgeFadeIn`.
 *
 * The animation durations match the curve used by Material Design's
 * "standard" easing and stay short enough that the slider still feels
 * responsive when scrubbing quickly.
 * ────────────────────────────────────────────────────────────────────── */
.react-flow__node {
  transition:
    transform 450ms cubic-bezier(0.16, 1, 0.3, 1),
    width 350ms cubic-bezier(0.16, 1, 0.3, 1),
    height 350ms cubic-bezier(0.16, 1, 0.3, 1);
  animation: nodeFadeIn 280ms ease-out both;
}

/* Group containers shouldn't visibly fade in β€” the children inside already
 * carry the animation. Animating their opacity makes the inner nodes feel
 * "doubled up" during the transition. */
.react-flow__node-group {
  animation: none;
}

@keyframes nodeFadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.react-flow__edges {
  /* Fade the entire edges layer when the topology changes so that paths
   * which jump to wildly different routes don't look broken mid-animation. */
  transition: opacity 220ms ease-out;
}

.react-flow__edge {
  animation: edgeFadeIn 320ms ease-out both;
}

@keyframes edgeFadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Respect the OS reduced-motion preference. */
@media (prefers-reduced-motion: reduce) {
  .react-flow__node,
  .react-flow__edges,
  .react-flow__edge {
    transition: none !important;
    animation: none !important;
  }
}