feat: add zoom in/out/fit controls to network map

This commit is contained in:
Graham McIntire 2026-03-14 18:31:35 -05:00
parent a1c5d593dc
commit f13ff205ce
No known key found for this signature in database
2 changed files with 65 additions and 0 deletions

View file

@ -613,6 +613,41 @@ const NetworkMap = {
}
},
_initControls(this: any) {
const ZOOM_STEP = 0.25
const zoomIn = document.getElementById('cy-zoom-in')
const zoomOut = document.getElementById('cy-zoom-out')
const fit = document.getElementById('cy-fit')
if (zoomIn) {
zoomIn.addEventListener('click', () => {
if (!this.cy) return
this.cy.zoom({
level: Math.min(this.cy.zoom() + ZOOM_STEP, this.cy.maxZoom()),
renderedPosition: { x: this.cy.width() / 2, y: this.cy.height() / 2 }
})
})
}
if (zoomOut) {
zoomOut.addEventListener('click', () => {
if (!this.cy) return
this.cy.zoom({
level: Math.max(this.cy.zoom() - ZOOM_STEP, this.cy.minZoom()),
renderedPosition: { x: this.cy.width() / 2, y: this.cy.height() / 2 }
})
})
}
if (fit) {
fit.addEventListener('click', () => {
if (!this.cy) return
this.cy.fit(undefined, 50)
})
}
},
initializeCytoscape(this: any, topology: any) {
const isDark = document.documentElement.getAttribute('data-theme') === 'dark'
@ -1011,6 +1046,8 @@ const NetworkMap = {
'label': data.label || ''
})
})
this._initControls()
},
updateTopology(this: any, topology: any) {

View file

@ -180,6 +180,34 @@
data-topology={Jason.encode!(@topology)}
>
</div>
<!-- Zoom Controls -->
<div class="absolute bottom-4 left-4 flex flex-col gap-1 z-10">
<button
id="cy-zoom-in"
type="button"
title="Zoom in"
class="flex items-center justify-center w-8 h-8 bg-white dark:bg-gray-700 border border-gray-200 dark:border-white/10 rounded shadow-sm text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-white transition-colors"
>
<.icon name="hero-plus" class="h-4 w-4" />
</button>
<button
id="cy-zoom-out"
type="button"
title="Zoom out"
class="flex items-center justify-center w-8 h-8 bg-white dark:bg-gray-700 border border-gray-200 dark:border-white/10 rounded shadow-sm text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-white transition-colors"
>
<.icon name="hero-minus" class="h-4 w-4" />
</button>
<button
id="cy-fit"
type="button"
title="Fit to screen"
class="flex items-center justify-center w-8 h-8 bg-white dark:bg-gray-700 border border-gray-200 dark:border-white/10 rounded shadow-sm text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 hover:text-gray-900 dark:hover:text-white transition-colors"
>
<.icon name="hero-arrows-pointing-out" class="h-4 w-4" />
</button>
</div>
<!-- Node Detail Panel (slide-out) -->
<%= if @selected_node_detail do %>