ui Object
The ui object is available inside every UI script (.ui.js) as a local parameter. It is the primary interface for creating and managing all visual elements in a widget.
Availability
ui is only available in UI scripts. It is injected as a local parameter at execution time and is accessible inside any callback that closes over it (such as ipcRenderer.on(...) handlers).
setTimeout, setInterval, clearTimeout, and clearInterval are not available in UI scripts. Schedule time-based work from the Main script and send data via ipcMain.send().
UI scripts must end with .ui.js
The engine only executes files whose name ends in .ui.js (e.g. clock.ui.js, script.ui.js). Any other extension is rejected with an error and the script is not run.
Table of Contents
Batch Updates
Every add*, setElementProperties, and removeElements* call triggers a redraw by default. When adding or updating many elements at once, wrap the calls in beginUpdate / endUpdate to defer all redraws to a single pass.
Starts a batched update. All redraws triggered by subsequent add*, setElementProperties, and removeElements calls are suppressed until ui.endUpdate() is called.
Calls can be nested. Each beginUpdate must be paired with a matching endUpdate. The redraw fires when the outermost pair is closed.
ui.beginUpdate();
ui.addText({ id: "title", text: "Loading...", x: 16, y: 14 });
ui.addBar({ id: "bar", value: 0, x: 16, y: 40, width: 260, height: 8 });
ui.addShape({ id: "bg", shapeType: "rectangle", x: 0, y: 0, width: 300, height: 200, fillColor: "rgb(20,20,20)" });
ui.endUpdate(); // All three elements rendered at onceEnds a batched update and triggers a single redraw with all pending changes applied.
ui.beginUpdate();
// ... add or update elements ...
ui.endUpdate();Adding Elements
All add* methods take a single options object. Passing no argument or a non-object throws a TypeError. Each method links to a dedicated page for the full list of available properties.
Creates a text element. See addText Options for all available properties.
ui.addText({
id: "label",
text: "Hello Novadesk",
x: 16, y: 14,
width: 260, height: 28,
fontSize: 16,
fontColor: "rgb(230,230,230)"
});Adds an image element. Supports local files, HTTP/HTTPS URLs, and 9-slice scaling. See addImage Options.
ui.addImage({
id: "logo",
path: "./assets/logo.png",
x: 16, y: 16,
width: 64, height: 64
});Adds a 2D vector shape. Supported shape types are "rectangle", "ellipse", "line", "arc", "curve", and "path". See addShape Options.
ui.addShape({
id: "card",
shapeType: "rectangle",
x: 16, y: 16,
width: 260, height: 80,
fillColor: "rgba(35,35,35,220)",
strokeColor: "rgba(255,255,255,40)",
strokeWidth: 1,
radiusX: 10, radiusY: 10
});Creates an interactive text input field. See addInputBox Options for all available properties.
ui.addInputBox({
id: "search",
placeholder: "Type to search...",
x: 16, y: 50,
width: 260, height: 36
});Adds a progress bar element. The value property accepts a normalized 0.0–1.0 range. See addBar Options.
ui.addBar({
id: "cpu-bar",
x: 16, y: 60,
width: 260, height: 8,
value: 0.65,
barColor: "rgb(0,180,255)",
barCornerRadius: 4
});Adds a rounded arc element for circular progress indicators. See addRoundLine Options.
ui.addRoundLine({
id: "cpu-arc",
x: 60, y: 60,
width: 120, height: 120,
value: 0.65,
lineColor: "rgb(0,180,255)",
lineColorBg: "rgba(255,255,255,0.1)",
thickness: 8,
startAngle: -135,
totalAngle: 270,
capType: "round"
});Adds a scrolling line graph supporting multiple overlaid data series. See addLine Options.
ui.addLine({
id: "cpu-line",
x: 16, y: 80,
width: 260, height: 60,
lineColor: "rgb(0,180,255)",
rangeMin: 0, rangeMax: 100
});Adds a filled area graph element. See addAreaGraph Options.
ui.addAreaGraph({
id: "mem-area",
x: 16, y: 80,
width: 260, height: 60,
lineColor: "rgb(0,255,136)",
fillColor: "rgba(0,255,136,0.15)"
});Adds a bar-by-bar histogram supporting dual-channel data. See addHistogram Options.
ui.addHistogram({
id: "spectrum",
x: 16, y: 80,
width: 260, height: 60,
primaryColor: "rgb(0,255,136)"
});Adds a frame-based sprite sheet element for meters, digit displays, and sprite animations. See addBitmap Options.
ui.addBitmap({
id: "digits",
bitmapImageName: "./assets/digits.png",
bitmapFrames: 10,
bitmapExtend: true,
value: 42
});Adds an image-based rotator element for gauge needles and dials. See addRotator Options.
ui.addRotator({
id: "needle",
rotatorImageName: "./assets/needle.png",
value: 0.75,
minValue: 0, maxValue: 1,
startAngle: -135,
rotationAngle: 270,
offsetX: 10, offsetY: 90
});Adds a flex layout container that positions and clips child elements. The id property is required. See addLayoutBox Options.
Children are defined as plain objects with an elementType property set to the element type name (e.g. "text", "image", "shape", "bar", "layoutbox"). Nested layout boxes are supported.
TIP
ui.addLayoutBox always triggers one redraw to finalize layout metadata even inside a beginUpdate / endUpdate block. This is expected behavior.
ui.addLayoutBox({
id: "card",
x: 16, y: 16,
width: 260, height: 80,
backgroundColor: "rgba(30,30,40,0.9)",
borderRadius: 8,
flexDirection: "column",
gap: 8,
padding: 12,
children: [
{ elementType: "text", id: "title", text: "CPU", fontSize: 14, fontColor: "rgb(255,255,255)" },
{ elementType: "bar", id: "bar", value: 0.5, barColor: "rgb(0,180,255)", height: 6 }
]
});Updating Elements
Updates one or more properties on an existing element. Only the properties included in props are changed — all other properties retain their current values.
If no element with the given id exists, the call is a silent no-op and returns undefined.
PARAMETERS
ui.setElementProperties("label", {
text: "CPU: 72%",
fontColor: "rgb(0,180,255)"
});
// Also works for a single property
ui.setElementProperties("cpu-bar", { value: 0.72 });Updates a single property on an existing element. This is a convenience wrapper around setElementProperties.
Legacy form
setElementProperty(id, optionsObject) (two arguments, second is an object) is also accepted and behaves identically to setElementProperties(id, optionsObject).
PARAMETERS
ui.setElementProperty("cpu-bar", "value", 0.75);
ui.setElementProperty("label", "fontColor", "rgb(255,0,0)");Updates every element that shares the given group value with the same set of properties in one call. Also available as ui.setElementPropertyByGroup(group, props).
PARAMETERS
// Hide all elements tagged with group: "stats"
ui.setElementPropertiesByGroup("stats", { show: false });
// Update color of all label elements in a group
ui.setElementPropertiesByGroup("labels", { fontColor: "rgb(255,100,100)" });Animates supported properties of an existing element. Calling animate on an element that is already animating replaces the running animation immediately.
Required properties: id and either to (for a simple transition) or keyframes (for keyframe animation). The two are mutually exclusive.
See animate Options for the full property reference including all easing functions.
Throws on missing or invalid options
animate throws a TypeError if id is missing, if the element is not found, if to contains no supported properties, or if keyframes is malformed.
// Simple transition
ui.animate({
id: "label",
duration: 400,
easing: "easeOutCubic",
to: { x: 100, y: 50 }
});
// Keyframe animation
ui.animate({
id: "dot",
duration: 1000,
easing: "linear",
iterationCount: "infinite",
keyframes: [
{ offset: 0, x: 0 },
{ offset: 0.5, x: 200 },
{ offset: 1, x: 0 }
]
});Querying Elements
Reads a single property value from an existing element. Throws TypeError if fewer than two arguments are provided.
Properties readable on all element types include: id, x, y, width, height, show, group, container, rotate, antiAlias, pixelHitTest, backgroundColor, backgroundColorRadius, bevelType, bevelWidth, bevelColor, bevelColor2, padding, transformMatrix, tooltipText, and more.
Type-specific readable properties include text, fontSize, fontColor, value, path, fillColor, strokeColor, and others depending on element type.
PARAMETERS
any The property value if found. Returns null if no element with that ID exists. Returns undefined if the element exists but the property name is not recognized for that element type.// Read text from an input box
const query = ui.getElementProperty("search", "text");
console.log("Search input:", query);
// Check if element is visible
const visible = ui.getElementProperty("panel", "show");
// Returns null if element doesn't exist
const result = ui.getElementProperty("nonexistent", "x");
// result === nullChecks whether an element with the given ID currently exists in the widget. Throws TypeError if no argument is provided.
PARAMETERS
boolean true if an element with that ID exists, false otherwise.if (ui.isElementExist("cpu-bar")) {
ui.setElementProperty("cpu-bar", "value", 0.5);
} else {
ui.addBar({ id: "cpu-bar", x: 16, y: 60, width: 260, height: 8 });
}Removing Elements
Removes a single element by its ID. Safe to call with an ID that does not exist.
PARAMETERS
boolean true if the element was found and removed, false if no element with that ID exists.const removed = ui.removeElementById("old-label");
if (!removed) {
console.log("Element did not exist");
}Removes one or more elements. The behavior depends on what is passed:
| Argument | Behavior |
|---|---|
No argument / null / undefined | Removes all elements from the widget |
string | Removes the single element with that ID |
string[] | Removes all elements whose IDs are in the array |
Calling with no argument clears the entire widget
ui.removeElements() with no argument removes every element. Use ui.removeElementById() when you intend to target a specific element.
PARAMETERS
// Remove specific elements
ui.removeElements(["img1", "text3"]);
// Remove a single element
ui.removeElements("label");
// Remove everything
ui.removeElements();Removes all elements that share the given group value. Throws TypeError if no argument is provided.
PARAMETERS
ui.removeElementsByGroup("stats");Practical Examples
Building an initial UI layout
ui.beginUpdate();
ui.addShape({
id: "bg",
shapeType: "rectangle",
x: 0, y: 0, width: 300, height: 120,
fillColor: "rgb(20,20,28)"
});
ui.addText({
id: "title",
text: "System Monitor",
x: 16, y: 12,
width: 268, height: 24,
fontSize: 15,
fontColor: "rgb(230,230,230)"
});
ui.addBar({
id: "cpu-bar",
x: 16, y: 48,
width: 268, height: 8,
value: 0,
barColor: "rgb(0,180,255)",
barCornerRadius: 4
});
ui.addText({
id: "cpu-label",
text: "CPU: 0%",
x: 16, y: 64,
width: 268, height: 20,
fontSize: 12,
fontColor: "rgba(200,200,200,180)"
});
ui.endUpdate();Updating elements from an IPC message
ipcRenderer.on("stats-update", (event, payload) => {
ui.beginUpdate();
ui.setElementProperties("cpu-bar", { value: payload.cpu / 100 });
ui.setElementProperties("cpu-label", { text: "CPU: " + payload.cpu + "%" });
ui.endUpdate();
});Rebuilding a list on data change
ipcRenderer.on("list-update", (event, payload) => {
ui.beginUpdate();
ui.removeElementsByGroup("list-item");
payload.items.forEach((item, i) => {
ui.addText({
id: "item-" + i,
group: "list-item",
text: item.label,
x: 16,
y: 40 + i * 28,
width: 268, height: 24,
fontSize: 13,
fontColor: "rgb(200,200,200)"
});
});
ui.endUpdate();
});Conditional element creation
function ensureElement(id) {
if (!ui.isElementExist(id)) {
ui.addText({ id, text: "", x: 16, y: 80, width: 268, height: 20, fontSize: 12, fontColor: "rgb(180,180,180)" });
}
}
ensureElement("status-label");
ui.setElementProperty("status-label", "text", "Ready");