v0.7.1 (build 925)

Overview #

Helix/UserInterface lets you declaratively build and update UI trees inside a compositor window. This page is a usage guide focused on concepts and workflow.

For the full domain-based function reference, use Helix/UserInterface.

Import #

import * as UI from 'Helix/UserInterface';

Quick start #

import * as Compositor from 'Koya/Compositor';
import * as UI from 'Helix/UserInterface';

const win = await Compositor.createWindow({ role: 'overlay', anchor: 'top-left', size: { x: 320, y: 200 }, offset: { x: 100, y: 100 } });

const root = await UI.createElement(win, {
  id: 'root',
  renderable: { type: 'panel' },
  layout: { type: 'column', gap: 8, padding: { t: 8, r: 8, b: 8, l: 8 } },
  child: [
    { id: 'title', renderable: { type: 'text', string: 'Hello', size: 22, font: '/rom/fonts/SourceSans3-Regular.ttf' } },
    {
      renderable: { type: 'panel' },
      layout: { type: 'row', gap: 6 },
      item: { size: { x: 280, y: 64 } },
      child: [
        { renderable: { type: 'text', string: 'Row 1', size: 18, font: '/rom/fonts/SourceSans3-Regular.ttf' } },
        { renderable: { type: 'text', string: 'Row 2', size: 18, font: '/rom/fonts/SourceSans3-Regular.ttf' } }
      ]
    }
  ]
});
await UI.attachRoot(win, root);

const titleId = await UI.getElementById(win, 'title');
await UI.setTextString(win, titleId, 'Updated');

Mental model #

  • Element: a node in a per-window UI tree.
  • Renderable: visual payload (box, panel, sprite, text, mesh, circle, particles).
  • Layout: parent-driven placement (row, column, grid, none).
  • Item: child sizing/spacing rules inside parent layout.
  • Content alignment: where renderable sits inside the child slot.
  • Events: per-element hit-tested callbacks.
  1. Create a window (Koya/Compositor).
  2. Build UI elements with createElement.
  3. Attach a root with attachRoot.
  4. Resolve string ids once with getElementById.
  5. Keep numeric ids for runtime updates.

Opacity mode guidance #

  • propagate is the lower-cost path and is usually fine when child visuals do not overlap.
  • composite is the higher-cost path (offscreen render + sample), and is preferred when overlapping/stacked children are faded as a group.
  • In practice: if fades look muddy or "self-blended", switch that container to opacityMode: 'composite'.

Common patterns #

Declarative child trees #

  • Use child: [...] in createElement to define subtrees in one call.
  • Entries in child can be: options objects (new element) or existing numeric ids (attach existing element).

Resource paths #

  • Prefer /rom/... for bundled fonts, textures, and shaders.
  • Runtime-generated textures are typically /ram/....

Performance #

  • Resolve element names once, then use numeric ids.
  • Disable subtrees with setEnabled(..., false) when hidden.
  • Use clipping (clipToBounds or clipToMask) for container-like views.

Animation handoff #

  • For transition chains, you can omit time: 0.0 in the next clip and start it from onAnimationEnd.
  • When time: 0.0 is omitted, Koya captures the element's current visual state as the runtime start frame for that clip.

API reference map #

The reference page is split by domain, each with its own function list:

  • Create/attach/destroy
  • Naming and lookup
  • Layout, item, and alignment
  • Clipping and masking
  • Resources and shaders
  • Text helpers
  • Animation
  • Measurement
  • Event handlers