Dashboard Layouts

Build responsive dashboards where widgets depend on each other's dimensions.

Overview

Dashboards have complex layout dependencies. A sidebar resize affects content width, which affects chart dimensions, which affects table column widths. Inval tracks all of this automatically.

Example: Multi-Widget Dashboard

dashboard.ts TYPESCRIPT
import { input, node, batch } from '@blu3ph4ntom/inval'

// External inputs
const dashboardWidth = input(1200)
const sidebarWidth = input(300)
const zoomLevel = input(1)

// Content area
const contentWidth = node({
  dependsOn: { dash: dashboardWidth, sidebar: sidebarWidth },
  compute: ({ dash, sidebar }) => dash - sidebar
})

// Chart: 60% of content
const chartWidth = node({
  dependsOn: { content: contentWidth },
  compute: ({ content }) => content * 0.6
})

// Chart height scales with zoom
const chartHeight = node({
  dependsOn: { zoom: zoomLevel },
  compute: ({ zoom }) => 400 * zoom
})

// Table: 40% of content
const tableWidth = node({
  dependsOn: { content: contentWidth },
  compute: ({ content }) => content * 0.4
})

// Table row height scales with zoom
const tableRowHeight = node({
  dependsOn: { zoom: zoomLevel },
  compute: ({ zoom }) => 40 * zoom
})

// --- Usage ---

// Initial layout
chartWidth.get()    // 540
tableWidth.get()    // 360
chartHeight.get()   // 400
tableRowHeight.get() // 40

// Resize sidebar: content changes, chart and table both update
sidebarWidth.set(400)
chartWidth.get()    // 480
tableWidth.get()    // 320
// chartHeight and tableRowHeight NOT dirty

// Change zoom: only zoom-dependent nodes dirty
zoomLevel.set(1.5)
chartHeight.get()    // 600
tableRowHeight.get() // 60
// chartWidth and tableWidth NOT dirty

// Atomic resize
batch(() => {
  dashboardWidth.set(1400)
  sidebarWidth.set(350)
})

Tip

Notice how changing zoom doesn't invalidate chart width or table width. The dependency graph ensures only affected nodes recompute.