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.
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.
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.
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.
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.
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
Link grouping
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.
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.
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.
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.
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.
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.
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.
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