H3 components are passive layout builders for registered menu and player scripts. Each call returns an OpenMW layout; it does not create an element or own your state. Start with UI Layouts and Lifecycle, jump to a UI recipe for a complete surface, or use H3UI when you want recipes, player-configured appearance, tokens, and a style cascade above these primitives.
A content-only root uses ui.TYPE.Container so it sizes itself to its children. The default ui.TYPE.Widget is also valid, but needs explicit geometry.
Choose by job
| Need | Components |
|---|---|
| Basic layout shape | widget, container, row, column |
| Text, images, and spacing | text, image, spacer |
| Lists and repeated content | list, listItem, grid |
| Framed content | box, bookFrame, dialog, tooltip |
| Actions and indicators | button, iconButton, meter, itemSlot |
| State and input | toggle, slider, selector, numberInput, searchInput, textInput |
| Tabbed or expandable content | tabs, collapsible |
| Morrowind window chrome | headBlock, caption, pinButton, window |
Shared layout options
Most builders 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. Wrap them with async:callback. |
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; takes precedence over children. |
children | openmw.ui.LayoutOrElement[]? | Provide child layouts when content is absent. |
The builders shallow-copy props and external. They do not copy child layouts, textures, or caller state deeply.
Mount a component
local ui = require 'openmw.ui'
local column = require 'scripts.s3.components.column'
local text = require 'scripts.s3.components.text'
local util = require 'openmw.util'
ui.create {
type = ui.TYPE.Container,
layer = 'Windows',
props = {
position = util.vector2(80, 80),
},
content = ui.content {
column {
children = {
text {
text = 'Hello from H3',
},
},
},
},
}
Keep element when a callback changes layout state, then call element:update(). Rebuild the root for structural changes. The component tests provide larger executable constructions.