Skip to content
S3ctor’s S3cret St4sh
api

UI Components

Option contracts for H3UI's application-facing constructors and internal building blocks.

H3 components are passive layout builders. Application code normally reaches them through the H3UI facade:

local I = require 'openmw.interfaces'
local ui = I.H3UI.scope()

local layout = ui.column {
    gap = 8,
    ui.text 'Hello from H3',
    ui.button {
        label = 'Continue',
        onActivate = continue,
    },
}

The pages in this section document the option contracts behind those constructors. You should not need one require per component in ordinary mod code. Examples in this section assume ui is an H3UI scope. See Mounting interactive UI for attaching that scope to an OpenMW Element.

H3 components return normal OpenMW layouts; they do not create elements, choose layers, retain application state, or own a rendered surface. Most recipes do the same, but recipes that isolate a frequently rebuilt region may create a nested Element and require a child scope from scope.child(). Start with UI Layouts and Lifecycle, then use the application recipes for complete copyable surfaces.

Choose by job

NeedConstructors
Layout and spacingrow, column, spacer, divider
Text and imagestext, image
Lists and repeated contentlist, listItem, grid
Frames and surfacesbox, bookFrame, tooltip, window
Actions and indicatorsbutton, iconButton, meter, itemSlot
State and inputtoggle, slider, selector, numberInput, searchInput, textInput
Tabbed or expandable contenttabs, collapsible

widget, container, headBlock, caption, and pinButton remain documented because H3 itself and advanced component authors use them. They are not part of the normal application constructor surface.

Shared layout options

Most constructors accept these layout fields:

FieldTypeDescription
namestring?Name a child for lookup from its owning Content.
propstable?Set layout properties such as size, position, or visible.
externaltable?Set parent-facing properties such as grow or stretch.
eventstable?Supply low-level OpenMW callbacks when no semantic callback fits.
userDataany?Attach caller-owned data to a layout.
templateopenmw.ui.Template?Override the default template where supported.
contentopenmw.ui.Content?Provide child content where supported.
childrenopenmw.ui.LayoutOrElement[]?Provide child layouts where supported.

row and column also accept children directly in the array part of the options table:

ui.row {
    gap = 6,
    ui.text 'Name',
    ui.textInput { text = name, onChange = setName },
}

The builders shallow-copy props and external. They do not deeply copy child layouts, textures, or caller state.

Mount a component

local I = require 'openmw.interfaces'
local openmwUi = require 'openmw.ui'
local util = require 'openmw.util'

local layout = I.H3UI.column {
    gap = 4,
    I.H3UI.text 'Hello from H3',
}

local element = openmwUi.create {
    type = openmwUi.TYPE.Container,
    layer = 'Windows',
    props = {
        position = util.vector2(80, 80),
    },
    content = openmwUi.content { layout },
}

For interactive surfaces, create an H3UI scope with an element resolver. H3 redraws its own semantic mutations; use ui.setChildren() for localized structural replacement and rebuild the caller-owned root only when necessary.

The bundled component tests now separate small diagnostic probes from application-grade reference fixtures. The Magic menu, inventory panel, and mod configuration surfaces are intended to be useful examples as well as integration tests.