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
| Need | Constructors |
|---|---|
| Layout and spacing | row, column, spacer, divider |
| Text and images | text, image |
| Lists and repeated content | list, listItem, grid |
| Frames and surfaces | box, bookFrame, tooltip, window |
| Actions and indicators | button, iconButton, meter, itemSlot |
| State and input | toggle, slider, selector, numberInput, searchInput, textInput |
| Tabbed or expandable content | tabs, 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:
| Field | Type | Description |
|---|---|---|
name | string? | Name a child for lookup from its owning Content. |
props | table? | Set layout properties such as size, position, or visible. |
external | table? | Set parent-facing properties such as grow or stretch. |
events | table? | Supply low-level OpenMW callbacks when no semantic callback fits. |
userData | any? | Attach caller-owned data to a layout. |
template | openmw.ui.Template? | Override the default template where supported. |
content | openmw.ui.Content? | Provide child content where supported. |
children | openmw.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.