UI Overview
Everything lives in the electrobun/main/ui entrypoint. It is import-gated:
apps that never import it pay nothing for it.
import { live, signal, ui, createUIWindow } from "electrobun/main/ui";Warren has two renderers over one core: this page covers the GPU
renderer (main process, Dawn); the same reactivity, JSX, and control flow
also render into real DOM inside webviews via
electrobun/browser/ui. Store and
model code written against the primitives runs unchanged on both sides.
How rendering works
Section titled “How rendering works”Your components build a retained tree of nodes (boxes, text, native-layer anchors). Reactive props are fine-grained: each thunk prop becomes one effect that writes one tree property. A frame tick polls input and — only when something marked the tree dirty — runs layout, flattens the tree into an instance buffer, and issues one instanced draw call to the window’s Dawn surface. Idle UI does no layout, paint, or GPU work; hidden windows skip the tick entirely.
UIWindows are regular GpuWindows underneath —
same native window, same full-window WGPUView, same surface. The UI runtime
is a layer on top, not a different GPU stack.
createUIWindow
Section titled “createUIWindow”const uiWindow = await createUIWindow(options, app);Creates a GpuWindow, mounts the tree, and starts the frame tick. The app
callback builds the UI with the element API.
| Option | Type | Default | Purpose |
|---|---|---|---|
title |
string |
— | Window title. |
width, height |
number |
— | Initial content size. |
titleBarStyle |
"hidden" | "hiddenInset" | "default" |
"hiddenInset" |
hiddenInset keeps the window frame equal to the content area. |
transparent |
boolean |
false |
Alpha-composited window. Pair with an alpha background and a rounded root box for floating panels. |
alwaysOnTop |
boolean |
false |
Keep the window above normal windows. |
background |
string |
"#141420" |
Clear color behind the tree. Accepts #rgb, #rrggbb, #rrggbbaa. |
tickMs |
number |
8 |
Frame tick interval. Input polls every tick; rendering only on dirty ticks. |
Returns { window, context, dispose }:
window— the underlyingGpuWindow(show(),hide(),isVisible(),setPosition(),setSize(),setAlwaysOnTop(), …). Hiding the window suspends all UI work until it is shown again.context— the mount’sUiContext(tree, reactivefocusedId/hoveredId, handler registries). Mostly useful for advanced integrations and tests.dispose()— tears down the reactive scope and closes the window.
createUIView
Section titled “createUIView”const uiView = await createUIView(view, options, app);Mounts a tree into an existing WGPUView instead
of a whole window — the mechanism behind
<electrobun-ui> overlays. options accepts
background and tickMs. The view’s frame supplies size and pointer offset.
registerUIRoot
Section titled “registerUIRoot”const registration = registerUIRoot("overlay-name", { background: "#1b1b28" }, app);Mounts app into every
<electrobun-ui name="overlay-name"> tag that
appears in your webviews. Each tag instance gets its own tree. Views removed
by the page are detected and disposed. Call registration.dispose() to stop.
Input model
Section titled “Input model”- Pointer — native view events on macOS (move, press, release, wheel,
enter/exit), with a polling fallback elsewhere: hover enter/leave, press,
release, click. Mouse wheel scrolls the innermost
overflow: "scroll"container. A press outside any hittable node blurs focus. Nodes opt in via handlers (onClick,onPointerDown,onPointerUp,onPointerEnter,onPointerLeave). - Keyboard — native key events route to the focused node’s
onKeyDownfirst (bubbling through ancestors; returntrueto stop), then to window-level handlers registered withonKey(handler). On macOS, events carry the keyboard layout’s characters (e.chars). - Focus —
focusable: truenodes take focus on click;textInputautofocuses when asked.ctx.focusedId()is reactive. - Window dragging —
windowDrag: truenodes move the window when dragged; a press without movement still deliversonClick.
Coordinates and units
Section titled “Coordinates and units”All sizes and positions are logical points with the origin at the window
content’s top-left. Colors are hex strings (or 0xRRGGBBAA numbers).