This is an automated email from the ASF dual-hosted git repository.

zqr10159 pushed a commit to branch 2.0.0
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git

commit 446b18b603a0c308474a35d57142c5168ea3f745
Author: Logic <[email protected]>
AuthorDate: Sun May 31 08:06:19 2026 +0800

    fix(web-next): suppress empty topology legends
---
 web-next/app/topology/page.test.tsx               |   3 +
 web-next/app/topology/topology-page.tsx           | 135 ++++++++++++----------
 web-next/packages/hertzbeat-ui/src/index.test.tsx |  13 +++
 web-next/packages/hertzbeat-ui/src/index.tsx      |   4 +
 4 files changed, 92 insertions(+), 63 deletions(-)

diff --git a/web-next/app/topology/page.test.tsx 
b/web-next/app/topology/page.test.tsx
index 33ffd36fbd..07fde71da5 100644
--- a/web-next/app/topology/page.test.tsx
+++ b/web-next/app/topology/page.test.tsx
@@ -1677,6 +1677,9 @@ describe('topology page', () => {
     
expect(html).toContain('data-hz-topology-empty-meta-owner="hertzbeat-ui-empty-meta"');
     
expect(html).toContain('data-hz-topology-empty-source-owner="hertzbeat-ui-empty-source"');
     
expect(html).toContain('data-hz-topology-empty-time-scope-owner="hertzbeat-ui-empty-time-scope"');
+    
expect(html).not.toContain('data-topology-g6-legend-owner="hertzbeat-ui-g6-legend-dock"');
+    expect(html).not.toContain('data-hz-ui="topology-legend"');
+    expect(html).not.toContain('data-hz-topology-legend-section=');
     expect(html).not.toContain('data-topology-node-id="svc-checkout"');
     expect(html).not.toContain('checkout-api');
     expect(html).not.toContain('redis');
diff --git a/web-next/app/topology/topology-page.tsx 
b/web-next/app/topology/topology-page.tsx
index ea04862bef..62209c2af4 100644
--- a/web-next/app/topology/topology-page.tsx
+++ b/web-next/app/topology/topology-page.tsx
@@ -1152,71 +1152,80 @@ export default function TopologyPage({
     },
     [topologyG6Graph.nodes, t]
   );
+  const topologyHasVisibleNodes = topologyG6Graph.nodes.length > 0;
+  const topologyHasVisibleGraphEvidence = topologyHasVisibleNodes || 
topologyG6Graph.edges.length > 0;
   const topologyLegendSections = React.useMemo(
-    () => [
-      {
-        id: 'node-type',
-        label: t('topology.legend.node-type'),
-        items: topologyLegendNodeTypeItems
-      },
-      {
-        id: 'status',
-        label: t('topology.legend.status'),
-        items: [
-          {
-            id: 'healthy-node',
-            label: t('topology.legend.status.healthy'),
-            color: '#22c55e',
-            visualSource: 'hertzbeat-status-token' as const,
-            value: t('topology.legend.status.healthy-value')
-          },
-          {
-            id: 'warning-node',
-            label: t('topology.legend.status.warning'),
-            color: '#f59e0b',
-            visualSource: 'hertzbeat-status-token' as const,
-            value: t('topology.legend.status.warning-value')
-          },
-          {
-            id: 'critical-node',
-            label: t('topology.legend.status.critical'),
-            color: '#ef4444',
-            visualSource: 'hertzbeat-status-token' as const,
-            value: t('topology.legend.status.critical-value')
-          }
-        ]
-      },
-      {
-        id: 'interaction',
-        label: t('topology.legend.interaction'),
-        items: [
-          {
-            id: 'selected-node',
-            label: t('topology.legend.interaction.selected-node'),
-            color: '#e5edf8',
-            visualSource: 'hertzbeat-interaction-token' as const,
-            value: t('topology.legend.interaction.selected-node-value')
-          },
-          {
-            id: 'directional-edge',
-            label: t('topology.legend.interaction.directional-edge'),
-            color: '#94a3b8',
-            pattern: 'solid' as const,
-            visualSource: 'hertzbeat-edge-token' as const,
-            value: t('topology.legend.interaction.directional-edge-value')
-          },
-          {
-            id: 'dimmed-edge',
-            label: t('topology.legend.interaction.dimmed-edge'),
-            color: '#94a3b8',
-            pattern: 'muted' as const,
-            visualSource: 'hertzbeat-edge-token' as const,
-            value: t('topology.legend.interaction.dimmed-edge-value')
-          }
-        ]
+    () => {
+      const sections = [
+        {
+          id: 'node-type',
+          label: t('topology.legend.node-type'),
+          items: topologyLegendNodeTypeItems
+        }
+      ];
+      if (topologyHasVisibleNodes) {
+        sections.push({
+          id: 'status',
+          label: t('topology.legend.status'),
+          items: [
+            {
+              id: 'healthy-node',
+              label: t('topology.legend.status.healthy'),
+              color: '#22c55e',
+              visualSource: 'hertzbeat-status-token' as const,
+              value: t('topology.legend.status.healthy-value')
+            },
+            {
+              id: 'warning-node',
+              label: t('topology.legend.status.warning'),
+              color: '#f59e0b',
+              visualSource: 'hertzbeat-status-token' as const,
+              value: t('topology.legend.status.warning-value')
+            },
+            {
+              id: 'critical-node',
+              label: t('topology.legend.status.critical'),
+              color: '#ef4444',
+              visualSource: 'hertzbeat-status-token' as const,
+              value: t('topology.legend.status.critical-value')
+            }
+          ]
+        });
+      }
+      if (topologyHasVisibleGraphEvidence) {
+        sections.push({
+          id: 'interaction',
+          label: t('topology.legend.interaction'),
+          items: [
+            {
+              id: 'selected-node',
+              label: t('topology.legend.interaction.selected-node'),
+              color: '#e5edf8',
+              visualSource: 'hertzbeat-interaction-token' as const,
+              value: t('topology.legend.interaction.selected-node-value')
+            },
+            {
+              id: 'directional-edge',
+              label: t('topology.legend.interaction.directional-edge'),
+              color: '#94a3b8',
+              pattern: 'solid' as const,
+              visualSource: 'hertzbeat-edge-token' as const,
+              value: t('topology.legend.interaction.directional-edge-value')
+            },
+            {
+              id: 'dimmed-edge',
+              label: t('topology.legend.interaction.dimmed-edge'),
+              color: '#94a3b8',
+              pattern: 'muted' as const,
+              visualSource: 'hertzbeat-edge-token' as const,
+              value: t('topology.legend.interaction.dimmed-edge-value')
+            }
+          ]
+        });
       }
-    ],
-    [t, topologyLegendNodeTypeItems]
+      return sections;
+    },
+    [t, topologyHasVisibleGraphEvidence, topologyHasVisibleNodes, 
topologyLegendNodeTypeItems]
   );
   const topologyEdgeIds = React.useMemo(
     () => new Set(map.edges.map(edge => edge.id)),
diff --git a/web-next/packages/hertzbeat-ui/src/index.test.tsx 
b/web-next/packages/hertzbeat-ui/src/index.test.tsx
index fa75a423af..3768abb6b1 100644
--- a/web-next/packages/hertzbeat-ui/src/index.test.tsx
+++ b/web-next/packages/hertzbeat-ui/src/index.test.tsx
@@ -5285,6 +5285,19 @@ describe('@hertzbeat/ui', () => {
     expect(html).toContain('data-hz-topology-legend-item="healthy-node"');
   });
 
+  it('does not render a topology legend shell when every section is empty', () 
=> {
+    const html = renderToStaticMarkup(
+      <HzTopologyLegend
+        title="Legend"
+        boundary="flush"
+        density="canvas-dock"
+        sections={[{ id: 'node-type', label: 'Node type', items: [] }]}
+      />
+    );
+
+    expect(html).toBe('');
+  });
+
   it('renders a topology detail drawer for edge evidence and cross-signal 
handoffs', () => {
     const html = renderToStaticMarkup(
       <HzTopologyDetailDrawer
diff --git a/web-next/packages/hertzbeat-ui/src/index.tsx 
b/web-next/packages/hertzbeat-ui/src/index.tsx
index 9d2cf77344..c6455ec437 100644
--- a/web-next/packages/hertzbeat-ui/src/index.tsx
+++ b/web-next/packages/hertzbeat-ui/src/index.tsx
@@ -11206,6 +11206,10 @@ export function HzTopologyLegend({
   const isCanvasDock = density === 'canvas-dock';
   const visibleSections = sections.filter(section => section.items.length > 0);
 
+  if (visibleSections.length === 0) {
+    return null;
+  }
+
   return (
     <section
       {...props}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to