跪拜 Guibai
← All articles
Frontend · Data Visualization · Three.js

A React Scaffold That Turns Dashboard Assembly into Drag-and-Drop Configuration

By 柳杉 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Visualization dashboards for smart cities, factories, and ops centers share the same repetitive engineering: layout, scaling, routing, and config persistence. A framework that standardizes these layers means teams stop rewriting the same glue code and start treating dashboards as assembled configurations rather than bespoke pages.

Summary

Dashboard projects quickly outgrow hardcoded layouts. `@lius1314/visual-dashboard-scaffold` provides an assembly layer where chart blocks, 3D maps, and business components are registered once and then arranged via drag-and-drop in a visual editor. Pixel-based coordinates match design handoff directly, while autofit.js handles proportional scaling across 16:9, 21:9, 32:9, and portrait screens.

The scaffold handles multi-page routing with parameter merging, a scoped EventBus for cross-component communication, and a hybrid persistence strategy that splits small metadata into localStorage and page details into IndexedDB to avoid lag during frequent drag operations. Themes, backgrounds, card decorations, and fonts ship as built-in assets with a selector panel, and custom assets can be injected at runtime.

Configuration export produces a JSON snapshot that can be loaded as an initial config in production. The edit-mode UI stays usable because only the content canvas scales, not the tool panels. A built-in action system maps clicks on headers, footers, and chart blocks to page switches, event emissions, or custom handler calls registered by the host application.

Takeaways
Chart blocks, maps, and business components register by string ID and render wherever that ID appears in the layout config.
Layout uses pixel coordinates (x, y, w, h, zIndex) to match design specs directly, with autofit.js handling overall proportional scaling.
Multi-page dashboards use hash routing (`/#/page/:pageId`) with three-layer parameter merging: URL params override switchPage params, which override page config params.
State persistence splits small metadata into localStorage and page details into IndexedDB, with throttled writes during drag operations to prevent UI lag.
Edit mode scales only the content canvas, keeping toolbars and configuration panels at full size and clickable.
A scoped EventBus cleans up listeners automatically when a page unmounts, preventing stale cross-component communication.
An action system maps clicks to page switches, event emissions, or custom handlers registered by the host application.
Built-in themes, backgrounds, card decorations, headers, footers, and fonts ship with the npm package and must be synced to the host's public directory.
Exported JSON configurations serve as initial defaults that do not overwrite locally persisted edits on subsequent loads.
The scaffold targets React + TypeScript + Zustand + react-grid-layout + react-router-dom and is available on npm at v1.2.2.
Conclusions

Pixel-based layout is a deliberate rejection of responsive grid systems for dashboards. Designers hand off exact coordinates, and converting them to grid fractions adds friction without benefit when the final output is a fixed-canvas screen.

Hybrid persistence (localStorage + IndexedDB) is an underappreciated pattern. Dumping a large JSON blob into localStorage on every drag event guarantees jank; splitting metadata from page bodies and throttling writes solves this without introducing a backend.

Scaling only the content canvas in edit mode, not the entire viewport, is a small detail that determines whether a visual editor is actually usable. Shrinking tool panels alongside the canvas makes precise adjustments impossible.

Making initialConfig a one-time default rather than a persistent override protects non-technical users who tweak layouts in production. It acknowledges that the exported JSON is a starting point, not a source of truth.

The action system's `custom` handler type creates an extension point that keeps the scaffold agnostic about what happens when a user clicks something. Host applications own the business logic; the scaffold only routes the click.

Concepts & terms
Block Registration
A pattern where React components are associated with string IDs via a `registerBlock('id', Component)` call. The scaffold renders the matching component wherever that ID appears in the layout configuration, decoupling the framework from specific chart libraries.
Hybrid Persistence
A storage strategy that writes small, frequently-accessed metadata to localStorage while storing larger page detail objects in IndexedDB. This avoids the performance cost of serializing and writing large JSON blobs on every state change.
Scoped EventBus
An event system where listeners are tied to a scope (e.g., a specific page ID). When that scope is destroyed—such as navigating away from a page—all associated listeners are automatically removed, preventing memory leaks and stale event handling.
autofit.js
A JavaScript library that proportionally scales a DOM element to fit its container while maintaining aspect ratio. Commonly used in dashboard projects to make a fixed-design canvas adapt to different screen resolutions.
Pixel-Based Layout
A layout approach that positions elements using absolute pixel coordinates (x, y, width, height) rather than relative units or grid fractions. It matches design tools' output directly and is scaled as a whole for different screen sizes.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗