← Назад к Wiki
Developer Guide

Widget & Settings UI Development Guide

Widget & Settings UI Development Guide

🇺🇦 Українська версія

1. Dashboard Grid

UI Core builds the dashboard as CSS grid. Each module with RUNNING status and ui_profile != HEADLESS gets a cell. Size from manifest.json:

sizeWidthHeightUse case
1x11 col1 rowSimple indicator
2x12 col1 rowCompact status
2x22 col2 rowFull widget with chart
4x1full width1 rowHorizontal panel

2. Key Rule: Widget Lives in iframe

  • No 100vh — use width/height: 100%
  • No scroll — scrolling="no" set by parent
  • No parent DOM access — sandbox blocks it
  • No alert/confirm/prompt — blocked
  • No localStorage reliance — data from API only

3. Required CSS Template

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { width: 100%; height: 100%; overflow: hidden; background: transparent; }
.root { width: 100%; height: 100%; display: flex; flex-direction: column; padding: 14px 16px; gap: 10px; overflow: hidden; }

Forbidden:

body { min-height: 100vh; }    /* breaks layout */
body { overflow: auto; }       /* causes scroll */
.widget { position: fixed; }   /* escapes cell */

4. BASE URL

const BASE = window.location.pathname
  .replace(/\/(widget|settings)(\.html)?(\?.*)?$/, '');
// Use: fetch(BASE + '/status')

5. Adaptive Layouts

function checkLayout() {
  const root = document.getElementById('root');
  root.classList.toggle('compact', root.offsetHeight < 160);
  root.classList.toggle('wide', root.offsetWidth > 600);
}
window.addEventListener('resize', checkLayout);

6. Data from Module

async function load() {
  const data = await fetch(BASE + '/status').then(r => r.json());
  render(data);
}
load();
setInterval(load, 30_000);

7. Core API from Widget

const uiToken = new URLSearchParams(window.location.search).get('ui_token');
const devices = await fetch('http://localhost:7070/api/v1/devices', {
  headers: { 'Authorization': `Bearer ${uiToken}` }
}).then(r => r.json());

UI token: read-only (device.read, events.subscribe), TTL 1 hour.

8. Realtime: SSE

const es = new EventSource(BASE + '/events/stream');
es.addEventListener('state_changed', (e) => updateUI(JSON.parse(e.data)));

9. settings.html Rules

Displayed in a scrollable modal. overflow-y: auto allowed. Save via module API, not localStorage.

Checklist

  • html, body: width/height 100%, overflow hidden
  • No 100vh, no position: fixed
  • BASE computed from pathname
  • Error handling on all fetch calls
  • Auto-refresh with setInterval or SSE
  • Compact mode for height < 160px
Widget & Settings UI Development Guide | Wiki · Selena Home AI