Modern touch-first dashboard for Node-RED uibuilder, designed for a fixed 7-inch class landscape display (1280x720).
Layout zones:
- Top status bar: connection state, fault state, last message age.
- Main split area:
- Left: high-priority telemetry cards (voltage, current, RPM, thermal).
- Right: active page content (control panel, diagnostics, setup).
- Bottom glide indicator: swipe progress and active page markers.
Navigation model:
- Horizontal finger swipe switches full-width pages (
Overview,Controls,Lights,Setup). - Gesture starts on interactive controls are ignored to preserve taps, switches, sliders, and buttons.
- Swipe is accepted only after intentional horizontal movement threshold to avoid accidental page changes.
- Emergency action (
Stop All) always visible in control view.
AppTopStatusBarStatusGridControlPaneluseSwipePagesui/*shadcn-style primitives (Button,Card,Badge,Slider,Switch,Progress)
Hook: src/hooks/useUibuilder.ts
- Connects to namespace
/${VITE_UIBUILDER_URL}. - Uses uibuilder path
/uibuilder/vendor/socket.io. - Listens to both
uiBuilderanduiBuilderMsgevents. - Exposes
send(payload, topic)for command/control messages.
Control message example:
send(
{
type: 'control-update',
controls: nextState,
reason: 'fan-speed',
},
'controls',
)- Minimum touch target:
44px. - Font sizing tuned for readability at arm's length (
text-lgtotext-4xl). - Fixed canvas layout with controlled scaling using
useFixedScale. - Low-motion transitions only (no expensive animation loops).
This project does not use generic mobile responsiveness.
Instead:
- Design against a fixed base canvas:
1280x720. - Compute scale factor from viewport to base canvas.
- Apply a single transform scale to the entire dashboard frame.
- Clamp scale range to avoid tiny or giant controls.
- Show orientation guard screen when portrait is detected.
Benefits:
- Stable spacing and alignment.
- Predictable touch geometry.
- Less CSS complexity and fewer layout recalculations.
- Keep component tree shallow and memoize display components (
memo). - Avoid heavy box-shadows, blurs, and perpetual animations.
- Use coarse update intervals for non-critical UI timers.
- Batch control state updates before emitting over socket.
- Keep bundle lean with selective shadcn primitives only.
npm install
npm run devnpm run build
npm run deployOptional SCP deploy:
npm run deploy -- --scp