Skip to content

Attention

These examples document the attention behaviors from the canonical TopoViewer test-case catalog. Each section is generated from one test case and keeps the live viewport, topology YAML, and stylesheet YAML together.

Object focus

What This Demonstrates

Object focus is the default interactive attention pattern. Click the Checkout flow path, a node, or a link in the live viewport; the selected object is highlighted while unrelated context stays visible but muted. Click empty viewport space to clear the focus and return to the normal topology view.

Expected Result

The live viewport should render "Object focus" without blocking diagnostics. It should show: Click one topology object to highlight it while dimming the surrounding context. The test metadata expects graphNodes: 4, minVisibleEdges: 5.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Object focus

version: "0.2"
graph:
  id: attention-object-focus
  layers:
    - id: service
      labels:
        name: Service
  nodes:
    - id: client
      labels:
        role: endpoint
        name: Client
      data:
        severity: normal
      layers:
        - service
      position:
        - 80
        - 180
    - id: edge
      labels:
        role: gateway
        name: Edge
      data:
        severity: normal
      layers:
        - service
      position:
        - 270
        - 180
    - id: api
      labels:
        role: service
        name: API
      data:
        severity: critical
      layers:
        - service
      position:
        - 460
        - 180
    - id: cache
      labels:
        role: support
        name: Cache
      data:
        severity: normal
      layers:
        - service
      position:
        - 460
        - 320
  links:
    - id: link-client-edge
      source: client
      target: edge
      labels:
        link: service
        name: Client to edge
      layers:
        - service
    - id: link-edge-api
      source: edge
      target: api
      labels:
        link: service
        name: Edge to API
      layers:
        - service
    - id: link-api-cache
      source: api
      target: cache
      labels:
        link: support
        name: API to cache
      layers:
        - service
  paths:
    - id: checkout-flow
      sequence:
        - client
        - edge
        - api
      labels:
        path: service
        name: Checkout flow
      data:
        severity: critical
      layers:
        - service
attention:
  interactive: true
  clickMode: dim-context
version: "0.2"
layout:
  mode: manual
  width: 620
  height: 420
icons:
  endpoint:
    glyph: C
    fill: "#2563eb"
    stroke: "#bfdbfe"
  gateway:
    glyph: G
    fill: "#0f766e"
    stroke: "#99f6e4"
  service:
    glyph: API
    fill: "#dc2626"
    stroke: "#fecaca"
  support:
    glyph: S
    fill: "#64748b"
    stroke: "#cbd5e1"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      width: 86
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "endpoint"]
    style:
      icon: endpoint
  - selector: node[labels.role = "gateway"]
    style:
      icon: gateway
  - selector: node[labels.role = "service"]
    style:
      icon: service
  - selector: node[labels.role = "support"]
    style:
      icon: support
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.5
      targetArrowShape: none
      opacity: 0.72
  - selector: link[labels.link = "support"]
    style:
      lineDashPattern: 5 5
  - selector: path
    style:
      label: Checkout flow
      curveStyle: smooth-taxi
      lineColor: "#38bdf8"
      lineWidth: 4
      animated: true
      targetArrowShape: triangle

Change focus

What This Demonstrates

Change focus is a declarative attention query for operational change. This small topology starts with attention already applied: CORE-1 and the degraded core-1-core-2 link changed after the selected timestamp, so they are highlighted while the unchanged objects remain visible but muted.

Expected Result

The live viewport should render "Change focus" without blocking diagnostics. It should show: Focus objects with recent change metadata while preserving topology context. The test metadata expects graphNodes: 5, minVisibleEdges: 5.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Change focus

version: "0.2"
graph:
  id: attention-change-focus
  layers:
    - id: physical
      labels:
        name: Physical
    - id: control
      labels:
        name: Control
  nodes:
    - id: EDGE-1
      labels:
        node: router
        role: edge
        name: EDGE-1
      data:
        severity: normal
      layers:
        - physical
      position:
        - 80
        - 180
    - id: CORE-1
      labels:
        node: router
        role: core
        name: CORE-1
      data:
        severity: major
        changedAt: "2026-06-15T10:30:00Z"
        revision: 8
      layers:
        - physical
      position:
        - 250
        - 120
    - id: CORE-2
      labels:
        node: router
        role: core
        name: CORE-2
      data:
        severity: normal
      layers:
        - physical
      position:
        - 420
        - 180
    - id: PE-1
      labels:
        node: router
        role: pe
        name: PE-1
      data:
        severity: normal
      layers:
        - physical
      position:
        - 250
        - 300
    - id: NOC
      labels:
        node: controller
        role: control
        name: NOC
      data:
        severity: normal
        changedAt: "2026-06-01T08:00:00Z"
        revision: 3
      layers:
        - control
      position:
        - 590
        - 120
  links:
    - id: edge-core-1
      source: EDGE-1
      target: CORE-1
      labels:
        link: physical
        name: EDGE-1 to CORE-1
      layers:
        - physical
    - id: core-1-core-2
      source: CORE-1
      target: CORE-2
      labels:
        link: physical
        name: Changed core link
      data:
        status: degraded
        changedAt: "2026-06-15T10:30:00Z"
        revision: 8
      layers:
        - physical
    - id: core-1-pe-1
      source: CORE-1
      target: PE-1
      labels:
        link: physical
        name: CORE-1 to PE-1
      layers:
        - physical
    - id: edge-pe-1
      source: EDGE-1
      target: PE-1
      labels:
        link: physical
        name: EDGE-1 to PE-1
      layers:
        - physical
    - id: core-2-noc
      source: CORE-2
      target: NOC
      labels:
        link: control
        protocol: telemetry
        name: CORE-2 to NOC telemetry
      layers:
        - control
attention:
  query:
    changes:
      since: "2026-06-10T00:00:00Z"
    mode: dim-context
version: "0.2"
layout:
  mode: manual
  width: 700
  height: 420
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
  controller:
    glyph: NOC
    fill: "#f59e0b"
    stroke: "#fde68a"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "control"]
    style:
      icon: controller
      width: 92
      borderColor: "#facc15"
      backgroundColor: "#f59e0b"
  - selector: node[data.severity = "major"]
    style:
      borderColor: "#fed7aa"
      backgroundColor: "#f97316"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.6
      targetArrowShape: none
      opacity: 0.78
  - selector: link[labels.protocol = "telemetry"]
    style:
      label: Telemetry
      curveStyle: bezier
      lineColor: "#22c55e"
      lineDashPattern: 3 4
      targetArrowShape: triangle
  - selector: link[data.status = "degraded"]
    style:
      lineColor: "#f97316"
      lineWidth: 3

Region collapse

What This Demonstrates

Region collapse demonstrates progressive disclosure. The access metro region starts declaratively collapsed into one aggregate summary node; click the Access metro summary in the live viewport to expand the region and reveal its member nodes and internal links. Click the expanded region hull to collapse it back into the summary node.

Expected Result

The live viewport should render "Region collapse" without blocking diagnostics. It should show: Collapse a region into an aggregate summary, then click it to expand member nodes. The test metadata expects graphNodes: 2, minVisibleEdges: 1.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Region collapse

version: "0.2"
graph:
  id: attention-region-collapse
  layers:
    - id: physical
      labels:
        name: Physical
  nodes:
    - id: AGG-1
      labels:
        node: router
        role: aggregation
        name: AGG-1
      data:
        severity: major
      layers:
        - physical
      position:
        - 220
        - 130
    - id: ACC-1
      labels:
        node: router
        role: access
        name: ACC-1
      data:
        severity: normal
      layers:
        - physical
      position:
        - 90
        - 270
    - id: ACC-2
      labels:
        node: router
        role: access
        name: ACC-2
      data:
        severity: normal
      layers:
        - physical
      position:
        - 350
        - 270
    - id: PE-1
      labels:
        node: router
        role: pe
        name: PE-1
      data:
        severity: normal
      layers:
        - physical
      position:
        - 590
        - 190
  links:
    - id: agg-acc-1
      source: AGG-1
      target: ACC-1
      labels:
        link: access
        name: AGG-1 to ACC-1
      layers:
        - physical
    - id: agg-acc-2
      source: AGG-1
      target: ACC-2
      labels:
        link: access
        name: AGG-1 to ACC-2
      layers:
        - physical
    - id: agg-pe-1
      source: AGG-1
      target: PE-1
      labels:
        link: uplink
        name: AGG-1 to PE-1
      layers:
        - physical
  regions:
    - id: access-metro
      members:
        - AGG-1
        - ACC-1
        - ACC-2
      labels:
        region: metro
        name: Access metro
      layers:
        - physical
attention:
  aggregate:
    groups:
      - id: access-metro
        by: region
        regionId: access-metro
        label: Access metro
    expandOnClick: true
layout:
  mode: manual
  width: 720
  height: 430
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "pe"]
    style:
      borderColor: "#bbf7d0"
      backgroundColor: "#16a34a"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.8
      targetArrowShape: none
      opacity: 0.8
  - selector: link[labels.link = "uplink"]
    style:
      lineColor: "#22c55e"
      lineWidth: 2.6
  - selector: region
    style:
      backgroundColor: "#0ea5e922"
      borderColor: "#38bdf8aa"
      borderRadius: 6
      borderWidth: 1
      padding: 70
      minWidth: 420
      minHeight: 260
      zIndex: -20

Dense summary drill-down

What This Demonstrates

Dense summary drill-down keeps a busy topology useful without making zoom decide what the operator meant. The overview shows one summary per metro, including hidden node count, link count, and worst severity. The PE full mesh between metros is represented as counted aggregate links instead of a pile of individual transport links. Click a metro summary to inspect that region while the rest of the topology stays compressed; drag the expanded region hull to reposition its members, or click the hull to collapse it again.

Expected Result

The live viewport should render "Dense summary drill-down" without blocking diagnostics. It should show: Keep dense metro topologies readable with summary nodes, counted full-mesh links, and explicit click-to-expand drill-down. The test metadata expects graphNodes: 3, minVisibleEdges: 3, minRegions: 0.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Dense summary drill-down

version: '0.2'
graph:
  id: attention-dense-summary-drilldown
  layers:
    - id: physical
      labels:
        name: Physical
    - id: transport
      labels:
        name: Transport
  nodes:
    - id: north-pe-a
      labels: {role: pe, metro: north, tier: backbone, name: NORTH PE-A}
      layers: [physical, transport]
      position: [170, 135]
      data: {severity: major, status: degraded}
    - id: north-pe-b
      labels: {role: pe, metro: north, tier: backbone, name: NORTH PE-B}
      layers: [physical, transport]
      position: [310, 135]
      data: {severity: normal, status: up}
    - id: north-agg-a
      labels: {role: aggregation, metro: north, tier: aggregation, name: NORTH AGG}
      layers: [physical]
      position: [240, 230]
      data: {severity: minor, status: constrained}
    - id: north-edge-a
      labels: {role: edge, metro: north, tier: access, name: NORTH EDGE-A}
      layers: [physical]
      position: [165, 325]
      data: {severity: normal, status: up}
    - id: north-edge-b
      labels: {role: edge, metro: north, tier: access, name: NORTH EDGE-B}
      layers: [physical]
      position: [315, 325]
      data: {severity: normal, status: up}

    - id: east-pe-a
      labels: {role: pe, metro: east, tier: backbone, name: EAST PE-A}
      layers: [physical, transport]
      position: [610, 135]
      data: {severity: normal, status: up}
    - id: east-pe-b
      labels: {role: pe, metro: east, tier: backbone, name: EAST PE-B}
      layers: [physical, transport]
      position: [750, 135]
      data: {severity: normal, status: up}
    - id: east-agg-a
      labels: {role: aggregation, metro: east, tier: aggregation, name: EAST AGG}
      layers: [physical]
      position: [680, 230]
      data: {severity: normal, status: up}
    - id: east-edge-a
      labels: {role: edge, metro: east, tier: access, name: EAST EDGE-A}
      layers: [physical]
      position: [605, 325]
      data: {severity: normal, status: up}
    - id: east-edge-b
      labels: {role: edge, metro: east, tier: access, name: EAST EDGE-B}
      layers: [physical]
      position: [755, 325]
      data: {severity: normal, status: up}

    - id: west-pe-a
      labels: {role: pe, metro: west, tier: backbone, name: WEST PE-A}
      layers: [physical, transport]
      position: [1050, 135]
      data: {severity: critical, status: down}
    - id: west-pe-b
      labels: {role: pe, metro: west, tier: backbone, name: WEST PE-B}
      layers: [physical, transport]
      position: [1190, 135]
      data: {severity: normal, status: up}
    - id: west-agg-a
      labels: {role: aggregation, metro: west, tier: aggregation, name: WEST AGG}
      layers: [physical]
      position: [1120, 230]
      data: {severity: major, status: degraded}
    - id: west-edge-a
      labels: {role: edge, metro: west, tier: access, name: WEST EDGE-A}
      layers: [physical]
      position: [1045, 325]
      data: {severity: normal, status: up}
    - id: west-edge-b
      labels: {role: edge, metro: west, tier: access, name: WEST EDGE-B}
      layers: [physical]
      position: [1195, 325]
      data: {severity: normal, status: up}
  links:
    - id: north-pe-a-north-pe-b
      source: north-pe-a
      target: north-pe-b
      labels: {relation: regional-pe-mesh, name: North PE protection}
      layers: [transport]
    - id: north-pe-a-north-agg-a
      source: north-pe-a
      target: north-agg-a
      labels: {relation: metro-backbone, name: North PE-A to AGG}
      layers: [physical]
    - id: north-pe-b-north-agg-a
      source: north-pe-b
      target: north-agg-a
      labels: {relation: metro-backbone, name: North PE-B to AGG}
      layers: [physical]
    - id: north-agg-a-north-edge-a
      source: north-agg-a
      target: north-edge-a
      labels: {relation: access-uplink, name: North edge A uplink}
      layers: [physical]
    - id: north-agg-a-north-edge-b
      source: north-agg-a
      target: north-edge-b
      labels: {relation: access-uplink, name: North edge B uplink}
      layers: [physical]

    - id: east-pe-a-east-pe-b
      source: east-pe-a
      target: east-pe-b
      labels: {relation: regional-pe-mesh, name: East PE protection}
      layers: [transport]
    - id: east-pe-a-east-agg-a
      source: east-pe-a
      target: east-agg-a
      labels: {relation: metro-backbone, name: East PE-A to AGG}
      layers: [physical]
    - id: east-pe-b-east-agg-a
      source: east-pe-b
      target: east-agg-a
      labels: {relation: metro-backbone, name: East PE-B to AGG}
      layers: [physical]
    - id: east-agg-a-east-edge-a
      source: east-agg-a
      target: east-edge-a
      labels: {relation: access-uplink, name: East edge A uplink}
      layers: [physical]
    - id: east-agg-a-east-edge-b
      source: east-agg-a
      target: east-edge-b
      labels: {relation: access-uplink, name: East edge B uplink}
      layers: [physical]

    - id: west-pe-a-west-pe-b
      source: west-pe-a
      target: west-pe-b
      labels: {relation: regional-pe-mesh, name: West PE protection}
      layers: [transport]
    - id: west-pe-a-west-agg-a
      source: west-pe-a
      target: west-agg-a
      labels: {relation: metro-backbone, name: West PE-A to AGG}
      layers: [physical]
    - id: west-pe-b-west-agg-a
      source: west-pe-b
      target: west-agg-a
      labels: {relation: metro-backbone, name: West PE-B to AGG}
      layers: [physical]
    - id: west-agg-a-west-edge-a
      source: west-agg-a
      target: west-edge-a
      labels: {relation: access-uplink, name: West edge A uplink}
      layers: [physical]
    - id: west-agg-a-west-edge-b
      source: west-agg-a
      target: west-edge-b
      labels: {relation: access-uplink, name: West edge B uplink}
      layers: [physical]

    - id: north-pe-a-east-pe-a
      source: north-pe-a
      target: east-pe-a
      labels: {relation: inter-metro-full-mesh, name: North-East PE mesh 1}
      layers: [transport]
    - id: north-pe-a-east-pe-b
      source: north-pe-a
      target: east-pe-b
      labels: {relation: inter-metro-full-mesh, name: North-East PE mesh 2}
      layers: [transport]
    - id: north-pe-b-east-pe-a
      source: north-pe-b
      target: east-pe-a
      labels: {relation: inter-metro-full-mesh, name: North-East PE mesh 3}
      layers: [transport]
    - id: north-pe-b-east-pe-b
      source: north-pe-b
      target: east-pe-b
      labels: {relation: inter-metro-full-mesh, name: North-East PE mesh 4}
      layers: [transport]

    - id: north-pe-a-west-pe-a
      source: north-pe-a
      target: west-pe-a
      labels: {relation: inter-metro-full-mesh, name: North-West PE mesh 1}
      layers: [transport]
    - id: north-pe-a-west-pe-b
      source: north-pe-a
      target: west-pe-b
      labels: {relation: inter-metro-full-mesh, name: North-West PE mesh 2}
      layers: [transport]
    - id: north-pe-b-west-pe-a
      source: north-pe-b
      target: west-pe-a
      labels: {relation: inter-metro-full-mesh, name: North-West PE mesh 3}
      layers: [transport]
    - id: north-pe-b-west-pe-b
      source: north-pe-b
      target: west-pe-b
      labels: {relation: inter-metro-full-mesh, name: North-West PE mesh 4}
      layers: [transport]

    - id: east-pe-a-west-pe-a
      source: east-pe-a
      target: west-pe-a
      labels: {relation: inter-metro-full-mesh, name: East-West PE mesh 1}
      layers: [transport]
    - id: east-pe-a-west-pe-b
      source: east-pe-a
      target: west-pe-b
      labels: {relation: inter-metro-full-mesh, name: East-West PE mesh 2}
      layers: [transport]
    - id: east-pe-b-west-pe-a
      source: east-pe-b
      target: west-pe-a
      labels: {relation: inter-metro-full-mesh, name: East-West PE mesh 3}
      layers: [transport]
    - id: east-pe-b-west-pe-b
      source: east-pe-b
      target: west-pe-b
      labels: {relation: inter-metro-full-mesh, name: East-West PE mesh 4}
      layers: [transport]
  regions:
    - id: north-metro
      members: [north-pe-a, north-pe-b, north-agg-a, north-edge-a, north-edge-b]
      labels: {metro: north, name: NORTH metro}
      layers: [physical, transport]
    - id: east-metro
      members: [east-pe-a, east-pe-b, east-agg-a, east-edge-a, east-edge-b]
      labels: {metro: east, name: EAST metro}
      layers: [physical, transport]
    - id: west-metro
      members: [west-pe-a, west-pe-b, west-agg-a, west-edge-a, west-edge-b]
      labels: {metro: west, name: WEST metro}
      layers: [physical, transport]
attention:
  aggregate:
    groups:
      - id: north-metro
        by: region
        regionId: north-metro
        label: NORTH metro
      - id: east-metro
        by: region
        regionId: east-metro
        label: EAST metro
      - id: west-metro
        by: region
        regionId: west-metro
        label: WEST metro
    expandOnClick: true
  links:
    grouping:
      enabled: true
      threshold: 2
      by: [endpoints, layer]
      expandOnClick: true
toggles:
  - id: showEdgeLabels
    default: true
    labels:
      name: Edge labels
version: "0.2"
icons:
  pe:
    glyph: PE
    fill: '#6d28d9'
    stroke: '#ddd6fe'
  aggregation:
    glyph: A
    fill: '#0369a1'
    stroke: '#bae6fd'
  edge:
    glyph: E
    fill: '#0f766e'
    stroke: '#ccfbf1'
labelFields:
  - labels.name
  - label
  - count
stylesheet:
  - selector: node
    style:
      width: 76
      height: 58
      borderWidth: 1.5
      labelFontSize: 11
  - selector: node[labels.role = "pe"]
    style:
      icon: pe
      width: 92
      height: 64
      borderWidth: 2.5
      labelFontWeight: 800
      labelColor: '#4c1d95'
  - selector: node[labels.role = "aggregation"]
    style:
      icon: aggregation
      width: 84
      height: 60
      borderWidth: 2
      labelColor: '#075985'
  - selector: node[labels.role = "edge"]
    style:
      icon: edge
      labelColor: '#115e59'
  - selector: node[isAggregate = "true"]
    style:
      width: 176
      height: 104
      backgroundColor: '#1e1b4b'
      borderColor: '#c4b5fd'
      borderWidth: 3
      labelColor: '#f5f3ff'
      labelFontSize: 15
      labelFontWeight: 900
  - selector: link
    style:
      curveStyle: bezier
      controlPointStepSize: 40
      lineColor: '#94a3b8'
      lineWidth: 1.8
      opacity: 0.72
      targetArrowShape: none
  - selector: link[labels.relation = "inter-metro-full-mesh"]
    style:
      lineColor: '#7c3aed'
      lineWidth: 2.2
      opacity: 0.52
  - selector: link[aggregate = "true"]
    style:
      lineColor: '#7c3aed'
      lineWidth: 4
      lineDashPattern: 12 6
      labelColor: '#312e81'
      textBackgroundColor: '#ede9fe'
      textBackgroundOpacity: 0.96
      opacity: 0.95
  - selector: link[isLinkAggregate = "true"]
    style:
      lineColor: '#7c3aed'
      lineWidth: 4
      lineDashPattern: 12 6
      labelColor: '#312e81'
      textBackgroundColor: '#ede9fe'
      textBackgroundOpacity: 0.96
      opacity: 0.95
  - selector: region
    style:
      backgroundColor: '#0ea5e914'
      borderColor: '#38bdf8aa'
      borderWidth: 1.2
      borderRadius: 8
      selectable: true
      draggable: true
      zIndex: -30
  - selector: region[id = "north-metro"]
    style:
      minHeight: 300
      minWidth: 300
      padding: 58
  - selector: region[id = "east-metro"]
    style:
      minHeight: 300
      minWidth: 300
      padding: 58
  - selector: region[id = "west-metro"]
    style:
      minHeight: 300
      minWidth: 300
      padding: 58
layout:
  mode: manual
  width: 1360
  height: 460

Advanced zoom policy

What This Demonstrates

Advanced zoom policy is an optional host-controlled behavior for map-style overview/detail transitions. The recommended operator workflow is still explicit: click an aggregate summary to expand it, then click the expanded region hull or parent object to collapse it. Use zoom thresholds only when the embedding experience intentionally wants detail to follow viewport scale.

Expected Result

The live viewport should render "Advanced zoom policy" without blocking diagnostics. It should show: Optionally bind aggregate expansion to zoom thresholds when a host needs map-style overview/detail transitions. The test metadata expects graphNodes: 2, minVisibleEdges: 1, minRegions: 0.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Advanced zoom policy

version: "0.2"
graph:
  id: attention-advanced-zoom-policy
  layers:
    - id: physical
      labels:
        name: Physical
  nodes:
    - id: WEST-1
      labels:
        role: aggregation
        site: west
        name: WEST-1
      data:
        severity: normal
      layers:
        - physical
      position:
        - 0
        - 90
    - id: WEST-2
      labels:
        role: access
        site: west
        name: WEST-2
      data:
        severity: major
      layers:
        - physical
      position:
        - 220
        - 90
    - id: EAST-1
      labels:
        role: aggregation
        site: east
        name: EAST-1
      data:
        severity: normal
      layers:
        - physical
      position:
        - 720
        - 90
    - id: EAST-2
      labels:
        role: access
        site: east
        name: EAST-2
      data:
        severity: critical
      layers:
        - physical
      position:
        - 940
        - 90
  links:
    - id: west-access
      source: WEST-1
      target: WEST-2
      layers:
        - physical
      labels:
        name: West access
    - id: metro-backbone
      source: WEST-2
      target: EAST-1
      layers:
        - physical
      labels:
        name: Metro backbone
    - id: east-access
      source: EAST-1
      target: EAST-2
      layers:
        - physical
      labels:
        name: East access
  regions:
    - id: west-metro
      members:
        - WEST-1
        - WEST-2
      layers:
        - physical
      labels:
        name: West metro
    - id: east-metro
      members:
        - EAST-1
        - EAST-2
      layers:
        - physical
      labels:
        name: East metro
attention:
  aggregate:
    groups:
      - id: west-metro
        by: region
        regionId: west-metro
        label: West metro
      - id: east-metro
        by: region
        regionId: east-metro
        label: East metro
    expandOnClick: true
    viewport:
      collapseBelowZoom: 1
      expandAboveZoom: 1.35
version: "0.2"
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[isAggregate = "true"]
    style:
      width: 132
      height: 78
      backgroundColor: "#312e81"
      borderColor: "#c4b5fd"
      labelColor: "#f5f3ff"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 2.2
      targetArrowShape: none
      opacity: 0.82
  - selector: link[aggregate = "true"]
    style:
      lineColor: "#8b5cf6"
      lineWidth: 4
      lineDashPattern: "10 5"
  - selector: region
    style:
      backgroundColor: "#0ea5e922"
      borderColor: "#38bdf8aa"
      borderRadius: 6
      borderWidth: 1
      zIndex: -20
  - selector: region[id = "west-metro"]
    style:
      minHeight: 210
      minWidth: 330
      padding: 70
  - selector: region[id = "east-metro"]
    style:
      minHeight: 210
      minWidth: 330
      padding: 70
layout:
  mode: manual
  width: 1120
  height: 300

What This Demonstrates

Link grouping demonstrates threshold-based edge aggregation. Three transport links between the same two routers start as one summary link labeled 3 links; click the summary link to reveal each member as a Cytoscape-style bundled Bezier edge. Use the explicit Collapse 3 links control to return to the summary without turning member-edge selection into a hidden toggle.

Expected Result

The live viewport should render "Link grouping" without blocking diagnostics. It should show: Group parallel links by endpoint and layer when the count crosses a threshold. The test metadata expects graphNodes: 2.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Link grouping

version: "0.2"
graph:
  id: attention-link-grouping
  layers:
    - id: transport
      labels:
        name: Transport
  nodes:
    - id: PE-1
      labels:
        role: pe
        name: PE-1
      layers:
        - transport
      position:
        - 120
        - 150
    - id: PE-2
      labels:
        role: pe
        name: PE-2
      layers:
        - transport
      position:
        - 500
        - 150
  links:
    - id: pe-1-pe-2-a
      source: PE-1
      target: PE-2
      labels:
        media: fiber
        name: 100G A
      layers:
        - transport
    - id: pe-1-pe-2-b
      source: PE-1
      target: PE-2
      labels:
        media: fiber
        name: 100G B
      layers:
        - transport
    - id: pe-1-pe-2-c
      source: PE-1
      target: PE-2
      labels:
        media: fiber
        name: 100G C
      layers:
        - transport
attention:
  links:
    grouping:
      enabled: true
      threshold: 2
      by:
        - endpoints
        - layer
      expandOnClick: true
toggles:
  - id: showEdgeLabels
    default: true
    labels:
      name: Edge labels
version: "0.2"
icons:
  router:
    glyph: PE
    fill: "#2563eb"
    stroke: "#bfdbfe"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 86
      height: 62
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: link
    style:
      curveStyle: bezier
      controlPointStepSize: 34
      lineColor: "#64748b"
      lineWidth: 2.2
      targetArrowShape: none
      labelColor: "#1e293b"
      textBackgroundColor: "#f8fafc"
      textBackgroundOpacity: 0.95
  - selector: link[id = "pe-1-pe-2-a"]
    style:
      lineColor: "#0f766e"
      lineWidth: 3
  - selector: link[id = "pe-1-pe-2-b"]
    style:
      lineColor: "#2563eb"
      lineWidth: 3
  - selector: link[id = "pe-1-pe-2-c"]
    style:
      lineColor: "#dc2626"
      lineWidth: 3
  - selector: link[isLinkAggregate = "true"]
    style:
      lineColor: "#8b5cf6"
      lineWidth: 4
      lineDashPattern: "10 5"
      labelColor: "#312e81"
      textBackgroundColor: "#ede9fe"
      textBackgroundOpacity: 0.96
layout:
  mode: manual
  width: 720
  height: 360

Query primitives

What This Demonstrates

Query primitives demonstrates the general focus query surface. The topology declares stable IDs, labels, nested data, and link media metadata; the MkDocs attention block focuses CORE-1, all access nodes, objects with critical severity or fanout 12, and the fiber link selected through a stylesheet-compatible selector.

Expected Result

The live viewport should render "Query primitives" without blocking diagnostics. It should show: Focus by explicit IDs, labels, data fields, and stylesheet-compatible selectors. The test metadata expects graphNodes: 5, minVisibleEdges: 4.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Query primitives

version: "0.2"
graph:
  id: attention-query-primitives
  layers:
    - id: physical
      labels:
        name: Physical
    - id: control
      labels:
        name: Control
  nodes:
    - id: CORE-1
      labels:
        node: router
        role: core
        site: fra
        name: CORE-1
      data:
        severity: critical
        metrics:
          fanout: 12
      layers: [physical]
      position: [120, 150]
    - id: DIST-1
      labels:
        node: router
        role: distribution
        site: fra
        name: DIST-1
      data:
        severity: major
      layers: [physical]
      position: [300, 150]
    - id: ACCESS-1
      labels:
        node: router
        role: access
        site: fra
        name: ACCESS-1
      data:
        severity: normal
      layers: [physical]
      position: [500, 70]
    - id: ACCESS-2
      labels:
        node: router
        role: access
        site: fra
        name: ACCESS-2
      data:
        severity: normal
      layers: [physical]
      position: [500, 230]
    - id: NOC
      labels:
        node: controller
        role: control
        name: NOC
      data:
        severity: normal
      layers: [control]
      position: [300, 330]
  links:
    - id: core-dist
      source: CORE-1
      target: DIST-1
      labels:
        link: physical
        media: fiber
        name: CORE-1 to DIST-1 fiber
      layers: [physical]
    - id: dist-access-1
      source: DIST-1
      target: ACCESS-1
      labels:
        link: physical
        media: copper
        name: DIST-1 to ACCESS-1
      layers: [physical]
    - id: dist-access-2
      source: DIST-1
      target: ACCESS-2
      labels:
        link: physical
        media: copper
        name: DIST-1 to ACCESS-2
      layers: [physical]
    - id: noc-core
      source: NOC
      target: CORE-1
      labels:
        link: control
        protocol: telemetry
        media: management
        name: NOC telemetry to CORE-1
      layers: [control]
attention:
  query:
    ids: [CORE-1]
    labels:
      role: access
    data:
      severity: critical
      metrics.fanout: 12
    selectors:
      - link[labels.media = "fiber"]
    mode: dim-context
version: "0.2"
layout:
  mode: manual
  width: 720
  height: 420
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
  controller:
    glyph: NOC
    fill: "#f59e0b"
    stroke: "#fde68a"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "control"]
    style:
      icon: controller
      width: 92
      borderColor: "#facc15"
      backgroundColor: "#f59e0b"
  - selector: node[data.severity = "critical"]
    style:
      borderColor: "#fecaca"
      backgroundColor: "#dc2626"
  - selector: node[labels.role = "access"]
    style:
      borderColor: "#bbf7d0"
      backgroundColor: "#16a34a"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.7
      targetArrowShape: none
      opacity: 0.8
  - selector: link[labels.media = "fiber"]
    style:
      label: Fiber
      lineColor: "#38bdf8"
      lineWidth: 3
  - selector: link[labels.protocol = "telemetry"]
    style:
      label: Telemetry
      curveStyle: bezier
      lineColor: "#22c55e"
      lineDashPattern: 3 4
      targetArrowShape: triangle

Region focus

What This Demonstrates

Region focus uses graph.regions[].members as the declarative grouping source. The attention query focuses the access metro region, so its member nodes become prominent while the PE outside the region and the surrounding links stay as dimmed context.

Expected Result

The live viewport should render "Region focus" without blocking diagnostics. It should show: Focus a region and its member nodes while preserving surrounding context. The test metadata expects graphNodes: 4, minVisibleEdges: 3, minRegions: 1.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Region focus

version: "0.2"
graph:
  id: attention-region-focus
  layers:
    - id: physical
      labels:
        name: Physical
  nodes:
    - id: AGG-1
      labels:
        node: router
        role: aggregation
        name: AGG-1
      data:
        severity: major
      layers: [physical]
      position: [220, 130]
    - id: ACC-1
      labels:
        node: router
        role: access
        name: ACC-1
      data:
        severity: normal
      layers: [physical]
      position: [90, 270]
    - id: ACC-2
      labels:
        node: router
        role: access
        name: ACC-2
      data:
        severity: normal
      layers: [physical]
      position: [350, 270]
    - id: PE-1
      labels:
        node: router
        role: pe
        name: PE-1
      data:
        severity: normal
      layers: [physical]
      position: [590, 190]
  links:
    - id: agg-acc-1
      source: AGG-1
      target: ACC-1
      labels:
        link: access
        name: AGG-1 to ACC-1
      layers: [physical]
    - id: agg-acc-2
      source: AGG-1
      target: ACC-2
      labels:
        link: access
        name: AGG-1 to ACC-2
      layers: [physical]
    - id: agg-pe-1
      source: AGG-1
      target: PE-1
      labels:
        link: uplink
        name: AGG-1 to PE-1
      layers: [physical]
  regions:
    - id: access-metro
      members: [AGG-1, ACC-1, ACC-2]
      labels:
        region: metro
        name: Access metro
      layers: [physical]
attention:
  query:
    regionIds: [access-metro]
    mode: dim-context
layout:
  mode: manual
  width: 720
  height: 430
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "pe"]
    style:
      borderColor: "#bbf7d0"
      backgroundColor: "#16a34a"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.8
      targetArrowShape: none
      opacity: 0.8
  - selector: link[labels.link = "uplink"]
    style:
      lineColor: "#22c55e"
      lineWidth: 2.6
  - selector: region
    style:
      backgroundColor: "#0ea5e922"
      borderColor: "#38bdf8aa"
      borderRadius: 6
      borderWidth: 1
      padding: 70
      minWidth: 420
      minHeight: 260
      zIndex: -20

Dependency focus

What This Demonstrates

Dependency focus uses directed links and path sequences as an adjacency graph. This example starts from CORE-1, walks two downstream hops, marks reached nodes as related, and leaves the links as dimmed context so the blast radius is visible without hiding the topology.

Expected Result

The live viewport should render "Dependency focus" without blocking diagnostics. It should show: Traverse directed topology relationships to show downstream blast radius. The test metadata expects graphNodes: 5, minVisibleEdges: 4.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Dependency focus

version: "0.2"
graph:
  id: attention-dependency-focus
  layers:
    - id: physical
      labels:
        name: Physical
    - id: control
      labels:
        name: Control
  nodes:
    - id: CORE-1
      labels:
        node: router
        role: core
        name: CORE-1
      data:
        severity: critical
      layers: [physical]
      position: [90, 190]
    - id: DIST-1
      labels:
        node: router
        role: distribution
        name: DIST-1
      data:
        severity: major
      layers: [physical]
      position: [300, 190]
    - id: ACCESS-1
      labels:
        node: router
        role: access
        name: ACCESS-1
      data:
        severity: normal
      layers: [physical]
      position: [540, 90]
    - id: ACCESS-2
      labels:
        node: router
        role: access
        name: ACCESS-2
      data:
        severity: normal
      layers: [physical]
      position: [540, 290]
    - id: NOC
      labels:
        node: controller
        role: control
        name: NOC
      data:
        severity: warning
      layers: [control]
      position: [300, 340]
  links:
    - id: core-dist
      source: CORE-1
      target: DIST-1
      labels:
        link: physical
        name: CORE-1 to DIST-1
      layers: [physical]
    - id: dist-access-1
      source: DIST-1
      target: ACCESS-1
      labels:
        link: physical
        name: DIST-1 to ACCESS-1
      layers: [physical]
    - id: dist-access-2
      source: DIST-1
      target: ACCESS-2
      labels:
        link: physical
        name: DIST-1 to ACCESS-2
      layers: [physical]
    - id: core-noc
      source: CORE-1
      target: NOC
      labels:
        link: control
        protocol: telemetry
        name: CORE-1 to NOC telemetry
      layers: [control]
attention:
  query:
    dependency:
      from: [CORE-1]
      direction: downstream
      depth: 2
    mode: dim-context
version: "0.2"
layout:
  mode: manual
  width: 760
  height: 430
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
  controller:
    glyph: NOC
    fill: "#f59e0b"
    stroke: "#fde68a"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "control"]
    style:
      icon: controller
      width: 92
      borderColor: "#facc15"
      backgroundColor: "#f59e0b"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.8
      targetArrowShape: triangle
      opacity: 0.82
  - selector: link[labels.protocol = "telemetry"]
    style:
      label: Telemetry
      curveStyle: bezier
      lineColor: "#22c55e"
      lineDashPattern: 3 4

Hide context

What This Demonstrates

Hide context mode is useful when context should be removed from the rendered view instead of muted. The topology marks two PE nodes with labels.role: pe; the attention query focuses that label and hides every non-matching node and link.

Expected Result

The live viewport should render "Hide context" without blocking diagnostics. It should show: Use hide-context mode when the focused set should be isolated instead of dimmed. The test metadata expects graphNodes: 2.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Hide context

version: "0.2"
graph:
  id: attention-hide-context
  layers:
    - id: physical
      labels:
        name: Physical
  nodes:
    - id: PE-1
      labels:
        node: router
        role: pe
        name: PE-1
      data:
        severity: major
      layers: [physical]
      position: [90, 170]
    - id: CORE-1
      labels:
        node: router
        role: core
        name: CORE-1
      data:
        severity: normal
      layers: [physical]
      position: [260, 100]
    - id: CORE-2
      labels:
        node: router
        role: core
        name: CORE-2
      data:
        severity: normal
      layers: [physical]
      position: [440, 100]
    - id: PE-2
      labels:
        node: router
        role: pe
        name: PE-2
      data:
        severity: minor
      layers: [physical]
      position: [610, 170]
    - id: RR-1
      labels:
        node: router
        role: route-reflector
        name: RR-1
      data:
        severity: normal
      layers: [physical]
      position: [350, 290]
  links:
    - id: pe-1-core-1
      source: PE-1
      target: CORE-1
      labels:
        link: physical
        name: PE-1 to CORE-1
      layers: [physical]
    - id: core-1-core-2
      source: CORE-1
      target: CORE-2
      labels:
        link: physical
        name: CORE-1 to CORE-2
      layers: [physical]
    - id: core-2-pe-2
      source: CORE-2
      target: PE-2
      labels:
        link: physical
        name: CORE-2 to PE-2
      layers: [physical]
    - id: rr-core
      source: RR-1
      target: CORE-1
      labels:
        link: control
        name: RR-1 to CORE-1
      layers: [physical]
attention:
  query:
    labels:
      role: pe
    mode: hide-context
version: "0.2"
layout:
  mode: manual
  width: 720
  height: 400
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "pe"]
    style:
      borderColor: "#bbf7d0"
      backgroundColor: "#16a34a"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.8
      targetArrowShape: none
      opacity: 0.82

Parent and label collapse

What This Demonstrates

Parent and label collapse shows the other aggregate group types. Service child nodes under PE-1 collapse by parent-child relationship, and access nodes collapse by labels.role: access; clicking the PE-1 services summary expands only that parent-derived group.

Expected Result

The live viewport should render "Parent and label collapse" without blocking diagnostics. It should show: Collapse parent-child objects and label-defined groups into aggregate summaries. The test metadata expects graphNodes: 4, minVisibleEdges: 3.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Parent and label collapse

version: "0.2"
graph:
  id: attention-parent-label-collapse
  layers:
    - id: physical
      labels:
        name: Physical
    - id: service
      labels:
        name: Service
  nodes:
    - id: CORE-1
      labels:
        node: router
        role: core
        name: CORE-1
      data:
        severity: normal
      layers: [physical, service]
      position: [650, 190]
    - id: PE-1
      labels:
        node: router
        role: pe
        name: PE-1
      data:
        severity: major
      layers: [physical, service]
      position: [380, 190]
    - id: SVC-A
      parent: PE-1
      labels:
        node: service
        role: service
        service: l3vpn
        name: VPN-A
      data:
        severity: critical
      layers: [service]
      position: [280, 120]
    - id: SVC-B
      parent: PE-1
      labels:
        node: service
        role: service
        service: l3vpn
        name: VPN-B
      data:
        severity: minor
      layers: [service]
      position: [280, 260]
    - id: ACC-1
      labels:
        node: router
        role: access
        name: ACC-1
      data:
        severity: normal
      layers: [physical]
      position: [90, 120]
    - id: ACC-2
      labels:
        node: router
        role: access
        name: ACC-2
      data:
        severity: major
      layers: [physical]
      position: [90, 260]
  links:
    - id: svc-a-core
      source: SVC-A
      target: CORE-1
      labels:
        link: service
        name: VPN-A to CORE-1
      layers: [service]
    - id: svc-b-core
      source: SVC-B
      target: CORE-1
      labels:
        link: service
        name: VPN-B to CORE-1
      layers: [service]
    - id: acc-1-pe
      source: ACC-1
      target: PE-1
      labels:
        link: access
        name: ACC-1 to PE-1
      layers: [physical]
    - id: acc-2-pe
      source: ACC-2
      target: PE-1
      labels:
        link: access
        name: ACC-2 to PE-1
      layers: [physical]
    - id: pe-core
      source: PE-1
      target: CORE-1
      labels:
        link: uplink
        name: PE-1 to CORE-1
      layers: [physical]
attention:
  aggregate:
    groups:
      - id: pe-services
        by: parent
        parentId: PE-1
        label: PE-1 services
      - id: access-role
        by: label
        key: role
        value: access
        label: Access nodes
    expandOnClick: true
version: "0.2"
layout:
  mode: manual
  width: 780
  height: 450
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
  service:
    glyph: SVC
    fill: "#7c3aed"
    stroke: "#ddd6fe"
labelFields:
  - labels.name
stylesheet:
  - selector: node
    style:
      icon: router
      width: 82
      height: 60
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[labels.role = "service"]
    style:
      icon: service
      width: 94
      height: 54
      backgroundColor: "#7c3aed"
      borderColor: "#ddd6fe"
  - selector: node[labels.role = "access"]
    style:
      borderColor: "#bbf7d0"
      backgroundColor: "#16a34a"
  - selector: link
    style:
      curveStyle: smooth-step
      lineColor: "#64748b"
      lineWidth: 1.8
      targetArrowShape: none
      opacity: 0.82
  - selector: link[labels.link = "service"]
    style:
      label: Service
      lineColor: "#a78bfa"
      lineWidth: 2.8
      targetArrowShape: triangle
  - selector: link[labels.link = "uplink"]
    style:
      label: Uplink
      lineColor: "#22c55e"
      lineWidth: 2.6

Aggregate badge and status

What This Demonstrates

Aggregate badge and status defaults make a collapsed group useful before drill-down. The summary node shows the hidden member count as a badge and the worst member severity as a status marker.

Expected Result

The live viewport should render "Aggregate badge and status" without blocking diagnostics. It should show: Collapsed aggregate summaries can expose hidden member count and worst severity as compact node cues. The test metadata expects graphNodes: 2, minVisibleEdges: 1.

What To Inspect

  • Review the attention state in the live viewport and compare it with the optional Attention YAML tab.
  • Check which objects stay prominent and which objects are dimmed, collapsed, or summarized.

Use When

Use this pattern when a dense graph needs focus, dimming, aggregation, or label-priority behavior.

Aggregate badge and status

version: "0.2"
graph:
  id: attention-aggregate-badge-status
  layers:
    - id: physical
      labels:
        name: Physical
  nodes:
    - id: ACC-1
      labels:
        role: access
        name: ACC-1
      data:
        severity: normal
      layers: [physical]
      position: [120, 110]
    - id: ACC-2
      labels:
        role: access
        name: ACC-2
      data:
        severity: critical
      layers: [physical]
      position: [120, 230]
    - id: AGG-1
      labels:
        role: aggregation
        name: AGG-1
      data:
        severity: major
      layers: [physical]
      position: [300, 170]
    - id: PE-1
      labels:
        role: pe
        name: PE-1
      data:
        severity: normal
      layers: [physical]
      position: [520, 170]
  links:
    - id: acc1-agg
      source: ACC-1
      target: AGG-1
      layers: [physical]
      labels:
        name: ACC-1 to AGG-1
    - id: acc2-agg
      source: ACC-2
      target: AGG-1
      layers: [physical]
      labels:
        name: ACC-2 to AGG-1
    - id: agg-pe
      source: AGG-1
      target: PE-1
      layers: [physical]
      labels:
        name: AGG-1 to PE-1
  regions:
    - id: access-region
      labels:
        region: access
        name: Access region
      members:
        - ACC-1
        - ACC-2
        - AGG-1
      layers: [physical]
attention:
  aggregate:
    groups:
      - id: access-region
        by: region
        regionId: access-region
        label: Access region
    expandOnClick: true
version: "0.2"
layout:
  mode: manual
  width: 650
  height: 360
icons:
  router:
    glyph: R
    fill: "#2563eb"
    stroke: "#bfdbfe"
stylesheet:
  - selector: node
    style:
      icon: router
      width: 92
      height: 68
      iconSize: 46
      borderWidth: 3
      labelColor: var(--topoviewer-fg-strong)
      labelFontWeight: 800
  - selector: node[isAggregate = "true"]
    style:
      shape: roundRectangle
      labelPosition: bottom
      badgeBackgroundColor: "#fee2e2"
      badgeColor: "#991b1b"
      badgeBorderColor: "#fecaca"
      statusPlacement: topRight
      statusSize: 13
      outlineColor: "#dc2626"
      outlineWidth: 4
      outlineOpacity: 0.72
      underlayColor: "#fee2e2"
      underlayPadding: 10
      underlayOpacity: 0.58
  - selector: node[labels.role = "pe"]
    style:
      backgroundColor: "#16a34a"
      borderColor: "#bbf7d0"
  - selector: link
    style:
      lineColor: "#94a3b8"
      lineWidth: 2
      targetArrowShape: none
  - selector: region
    style:
      backgroundColor: "#0ea5e922"
      borderColor: "#38bdf8aa"
      borderWidth: 1
      zIndex: -20
  - selector: region[id = "access-region"]
    style:
      minHeight: 250
      minWidth: 360
      padding: 64