UIElement
UIElement is the most fundamental and commonly used UI component in LDLib2.
All UI components inherit from it.
Conceptually, it is similar to the <div/> element in HTML: a general-purpose container that can be styled, laid out, and extended with behaviors.
Because of that, everything introduced in this page also applies to all other UI components in LDLib2—so please make sure to read it carefully.
Usages
var element = new UIElement();
element.style(style -> style.background(MCSprites.RECT));
element.layout(layout -> layout.width(40).height(40));
element.setFocusable(true)
element.addEventListener(UIEvents.MOUSE_DOWN, e -> e.currentElement.focus());
element.addClass("add-class")
element.removeClass("add-class")
root.addChild(element);
let element = new UIElement();
element.style(style => style.background(MCSprites.RECT));
element.layout(layout => layout.width(40).height(40));
element.setFocusable(true)
element.addEventListener(UIEvents.MOUSE_DOWN, e => e.currentElement.focus());
element.addClass("add-class")
element.removeClass("add-class")
root.addChild(element);
Xml
<element id="my_id" class="class1 class2" focusable="false" visible="true" active="true" style="background: #fff; width: 50">
<!-- add children here -->
<button text="click me!"/>
<inventory-slots/>
</element>
Styles
Layout
layout attributes are actually styles as well.
UIElement styles (include layouts) can be accessed as below:
Layout Properties
You'd better read Layout before using.
display
Controls whether the element participates in layout. FLEX enables flex layout, GRID enables grid layout, NONE removes the element from layout calculation, and CONTENTS doesn't affect layout but renders its children.
layout-direction
Sets the layout direction. Usually inherited from parent.
flex-basis
Sets the initial main size before flex grow/shrink. Supports point, percent, and auto.
flex
Makes the element flexible along the main axis.
flex-grow
Controls how much the element grows when extra space is available.
flex-shrink
Controls how much the element shrinks when space is insufficient.
flex-direction
Defines the main axis direction, e.g. ROW or COLUMN.
flex-wrap
Controls whether children wrap into multiple lines.
position
Sets positioning mode. RELATIVE participates in layout, ABSOLUTE does not affect siblings.
top / right / bottom / left / start / end / horizontal / vertical / all
Offsets used when position is RELATIVE or ABSOLUTE.
margin-*
*: top / right / bottom / left / start / end / horizontal / vertical / all
Sets outer spacing around the element.
padding-*
*: top / right / bottom / left / start / end / horizontal / vertical / all
Sets inner spacing between border and content.
gap-*
*: row / column / all
Sets spacing between children in flex layouts.
width
Sets element width. Supports point, percent, and auto modes.
height
Sets element height. Supports point, percent, and auto modes.
min-width / min-height
Sets the minimum size constraint.
max-width / max-height
Sets the maximum size constraint.
aspect-rate
Locks width–height ratio. Useful for square or icon elements.
align-items
Aligns children along the cross axis (container property).
justify-content
Aligns children along the main axis (container property).
align-self
Overrides cross-axis alignment for a single element.
align-content
Aligns wrapped lines when flex-wrap is enabled.
Grid Properties
To use grid layout, set display(TaffyDisplay.GRID) on the container element. Template properties define the grid structure on the container, while grid-row and grid-column are placed on child elements to control their positions.
grid-template-rows
Defines the explicit row tracks of a grid container.
Supported track sizes: Npx (fixed pixels), N% (percent), Nfr (fractional unit), auto, min-content, max-content, minmax(min, max), fit-content(limit), repeat(count, size), [name] (named line). Multiple tracks are space-separated.
layout.display(TaffyDisplay.GRID);
layout.gridTemplateRows("1fr 1fr 1fr"); // three equal rows
layout.gridTemplateRows("50px 1fr auto"); // fixed, flexible, auto
layout.gridTemplateRows("repeat(3, 100px)"); // three 100px rows
layout.gridTemplateRows("[header] 50px [content] 1fr [footer] 50px"); // named lines
grid-template-columns
Defines the explicit column tracks of a grid container. Uses the same track sizing syntax as grid-template-rows.
grid-template-areas
Assigns named areas to grid cells. Each quoted string represents a row; words within it name the cells in that row. Use . for empty cells. All rows must have the same number of cells.
grid-auto-rows
Sets the row track size for implicitly created rows — those not covered by grid-template-rows.
grid-auto-columns
Sets the column track size for implicitly created columns.
grid-auto-flow
Controls how auto-placed items fill the grid. ROW fills rows first (default); COLUMN fills columns first. ROW_DENSE / COLUMN_DENSE back-fill earlier gaps.
grid-row
Controls a child element's row placement within the grid container. Set this on the child, not the container.
Placement values: "1" (line number), "1 / 3" (start / end lines), "span 2" (span N rows), "1 / span 2" (start + span), "header" (named area row), "-1" (last line).
child.layout(layout -> layout.gridRow("1")); // row 1
child.layout(layout -> layout.gridRow("1 / 3")); // rows 1–3
child.layout(layout -> layout.gridRow("span 2")); // span 2 rows
child.layout(layout -> layout.gridRow("header")); // named area row
child.layout(layout -> layout.gridRow("-1")); // last row line
grid-column
Controls a child element's column placement within the grid container. Uses the same placement syntax as grid-row.
Basic Properties
background
Sets the background rendering of below the element, such as color, rect, image.
Check Texture in LSS for lss supports.
overflow
Controls how overflowing content is handled. If 'hidden', the content beyond the boundary will be hidden.
overlay
Controls overlay rendering drawn above the element content.
Check Texture in LSS for lss supports.
tooltips
Defines tooltip content displayed when hovering the element.
z-index
Controls the stacking order of the element. Higher values appear above lower ones.
opacity
Sets the transparency level of the element. 0 is fully transparent, 1 is fully opaque.
color
Tints the current element's background and overlay textures using an ARGB multiplier.
This tint is applied only to the current element and does not affect child elements.
overflow-clip
If element's overflow is set hidden, clips elements rendering based on given texture's red channel.
Check Texture in LSS for lss supports.
transform-2d
Applies 2D transformations such as translate, scale, or rotate.
transition
Defines animated transitions between property changes.
States
isVisible
When isVisible is set to false, the element and all of its children will no longer be rendered.
Unlike display: NONE, this does not affect layout calculation.
Elements with isVisible = false are also excluded from hit-testing, so many UI events (such as clicks) will not be triggered.
isActive
When isActive is set to false, the element may lose its interactive behavior—for example, buttons can no longer be clicked—and the element will no longer receive tick events.
Note
When isActive is set to false, a __disabled__ class is automatically added to the element.
You can use the following LSS selectors to style active and inactive states:
focusable
Elements are focusable: false by default. Some components, such as TextField, are focusable by design, but you can still manually change an element’s focusable state.
Only when focusable is set to true can an element be focused via focus() or by mouse interaction.
Note
When an element is in the focused state, a __focused__ class is automatically added.
You can style focused and unfocused states using the following LSS selectors:
hover state
When an element is hovered, a __hovered__ class is automatically added.
For CSS compatibility, you can use :hover as selector sugar, which is equivalent to .__hovered__.
isInternalUI
This is a special state that indicates whether an element is an internal part of a component.
For example, a button contains an internal text element used for rendering its label.
Semantically, internal elements are not allowed to be added, removed, or reordered directly.
However, you can still edit their styles and manage their child elements via the editor or XML.
In the editor, internal elements are displayed in gray in the hierarchy view.
In XML, you can access internal elements using the <internal index="..."/> tag, where index specifies which internal element to reference:
<button>
<!-- obtain the internal text component here -->
<internal index="0">
</internal>
</button>
In LSS, you can use :host and :internal to explicitly target host or internal elements. By default, selectors match both unless constrained.
Fields
Only public or protected fields that are externally observable or configurable are listed.
| Name | Type | Access | Description |
|---|---|---|---|
layoutNode |
YogaNode |
protected (getter) | Underlying Yoga node used for layout calculation. |
modularUI |
ModularUI |
private (getter) | The ModularUI instance this element belongs to. |
id |
String |
private (getter/setter) | Element ID, used by selectors and queries. |
classes |
Set<String> |
private (getter) | CSS-like class list applied to this element. |
styleBag |
StyleBag |
private (getter) | Stores resolved style candidates and computed styles. |
styles |
List<Style> |
private (getter) | Inline styles attached to this element. |
layoutStyle |
LayoutStyle |
private (getter) | Layout-related style wrapper (Yoga-based). |
style |
BasicStyle |
private (getter) | Basic visual styles (background, overlay tint color, opacity, zIndex, etc.). |
isVisible |
boolean |
private (getter/setter) | Whether the element is visible. |
isActive |
boolean |
private (getter/setter) | Whether the element participates in logic and events. |
focusable |
boolean |
private (getter/setter) | Whether the element can receive focus. |
isInternalUI |
boolean |
private (getter) | Marks internal (component-owned) elements. |
Methods
Layout & Geometry
| Method | Signature | Description |
|---|---|---|
getLayout() |
LayoutStyle |
Returns the layout style controller. |
layout(...) |
UIElement layout(Consumer<LayoutStyle>) |
Modify layout properties fluently. |
node(...) |
UIElement node(Consumer<YogaNode>) |
Directly modify the underlying Yoga node. |
getPositionX() |
float |
Absolute X position on screen. |
getPositionY() |
float |
Absolute Y position on screen. |
getSizeWidth() |
float |
Computed width of the element. |
getSizeHeight() |
float |
Computed height of the element. |
getContentX() |
float |
X position of content area (excluding border & padding). |
getContentY() |
float |
Y position of content area. |
getContentWidth() |
float |
Width of content area. |
getContentHeight() |
float |
Height of content area. |
adaptPositionToScreen() |
void |
Adjusts position to stay within screen bounds. |
adaptPositionToElement(...) |
void |
Adjusts position to stay inside another element. |
Tree Structure
| Method | Signature | Description |
|---|---|---|
getParent() |
UIElement |
Returns parent element, or null. |
getChildren() |
List<UIElement> |
Returns an unmodifiable list of children. |
addChild(...) |
UIElement addChild(UIElement) |
Adds a child element. |
addChildren(...) |
UIElement addChildren(UIElement...) |
Adds multiple children. |
removeChild(...) |
boolean removeChild(UIElement) |
Removes a child element. |
removeSelf() |
boolean |
Removes this element from its parent. |
clearAllChildren() |
void |
Removes all children. |
isAncestorOf(...) |
boolean |
Checks if this element is an ancestor of another. |
getStructurePath() |
ImmutableList<UIElement> |
Path from root to this element. |
Style & Classes
| Method | Signature | Description |
|---|---|---|
style(...) |
UIElement style(Consumer<BasicStyle>) |
Modify inline visual styles. |
lss(...) |
UIElement lss(String, Object) |
Apply a stylesheet-style property programmatically. |
addClass(...) |
UIElement addClass(String) |
Adds a CSS-like class. |
removeClass(...) |
UIElement removeClass(String) |
Removes a class. |
hasClass(...) |
boolean |
Checks if the class exists. |
getLocalStylesheets() |
List<Stylesheet> |
Returns local stylesheets attached to this element. |
addLocalStylesheet(...) |
UIElement addLocalStylesheet(Stylesheet) |
Adds a local stylesheet (self + descendants only). |
addLocalStylesheet(...) |
UIElement addLocalStylesheet(String) |
Parses and adds local stylesheet from LSS text. |
removeLocalStylesheet(...) |
UIElement removeLocalStylesheet(Stylesheet) |
Removes a local stylesheet from this element scope. |
clearLocalStylesheets() |
UIElement |
Removes all local stylesheets attached to this element. |
transform(...) |
UIElement transform(Consumer<Transform2D>) |
Applies a 2D transform. |
animation() |
StyleAnimation |
Creates a style animation targeting this element. See StyleAnimation. |
animation(a -> {}) |
StyleAnimation |
Runs animation setup immediately if ModularUI is valid, or once on MUI_CHANGED when it becomes valid. |
Focus & Interaction
| Method | Signature | Description |
|---|---|---|
focus() |
void |
Requests focus for this element. |
blur() |
void |
Clears focus if this element is focused. |
isFocused() |
boolean |
Returns true if this element is focused. |
isHover() |
boolean |
Returns true if mouse is directly over this element. |
isSelfOrChildHover() |
boolean |
Returns true if a slef or child is hovered. |
startDrag(...) |
DragHandler |
Starts a drag operation. |
Events
| Method | Signature | Description |
|---|---|---|
addEventListener(...) |
UIElement addEventListener(String, UIEventListener) |
Registers a bubble-phase event listener. |
addEventListener(..., true) |
UIElement addEventListener(String, UIEventListener, boolean) |
Registers a capture-phase listener. |
removeEventListener(...) |
void |
Removes an event listener. |
stopInteractionEventsPropagation() |
UIElement |
Stops mouse & drag event propagation. |
Usage
// Bubble-phase listener (default): fires after children handle the event
element.addEventListener(UIEvents.MOUSE_DOWN, event -> {
event.currentElement.focus();
});
// Capture-phase listener: fires before children handle the event
element.addEventListener(UIEvents.CLICK, event -> {
event.stopPropagation(); // prevent children from seeing this event
}, true);
// Removing a specific listener
UIEventListener listener = event -> { /* ... */ };
element.addEventListener(UIEvents.CLICK, listener);
element.removeEventListener(UIEvents.CLICK, listener);
// Stop all mouse/drag events from bubbling to parent elements
element.stopInteractionEventsPropagation();
Available Events
| Event | Description |
|---|---|
UIEvents.MOUSE_DOWN |
Mouse button pressed over the element |
UIEvents.MOUSE_UP |
Mouse button released |
UIEvents.CLICK |
Mouse clicked (pressed and released on the same element) |
UIEvents.DOUBLE_CLICK |
Mouse double-clicked |
UIEvents.MOUSE_MOVE |
Mouse moved while over the element |
UIEvents.MOUSE_ENTER |
Mouse pointer entered the element's bounds |
UIEvents.MOUSE_LEAVE |
Mouse pointer left the element's bounds |
UIEvents.MOUSE_WHEEL |
Mouse wheel scrolled |
UIEvents.DRAG_ENTER |
A drag operation entered this element |
UIEvents.DRAG_LEAVE |
A drag operation left this element |
UIEvents.DRAG_UPDATE |
Drag target position updated |
UIEvents.DRAG_SOURCE_UPDATE |
Drag source position updated |
UIEvents.DRAG_PERFORM |
Item was dropped on this element |
UIEvents.DRAG_END |
Drag operation ended |
UIEvents.FOCUS |
Element gained keyboard focus |
UIEvents.BLUR |
Element lost keyboard focus |
UIEvents.FOCUS_IN |
Focus moved into this element's subtree |
UIEvents.FOCUS_OUT |
Focus moved out of this element's subtree |
UIEvents.KEY_DOWN |
Keyboard key pressed |
UIEvents.KEY_UP |
Keyboard key released |
UIEvents.CHAR_TYPED |
A printable character was typed |
UIEvents.HOVER_TOOLTIPS |
Tooltip collection when hovering |
UIEvents.VALIDATE_COMMAND |
Slash command validation |
UIEvents.EXECUTE_COMMAND |
Slash command execution |
UIEvents.LAYOUT_CHANGED |
Layout was recalculated |
UIEvents.STYLE_CHANGED |
Styles were recomputed |
UIEvents.REMOVED |
Element was removed from its parent |
UIEvents.ADDED |
Element was added to a parent |
UIEvents.MUI_CHANGED |
ModularUI association changed |
UIEvents.TICK |
Periodic client-side tick |
Client–Server Sync & RPC
| Method | Signature | Description |
|---|---|---|
addSyncValue(...) |
UIElement |
Registers a synced value. |
removeSyncValue(...) |
UIElement |
Unregisters a synced value. |
addRPCEvent(...) |
RPCEmitter |
Registers an RPC event. |
sendEvent(...) |
void |
Sends an RPC event to server. |
sendEvent(..., callback) |
<T> void |
Sends an RPC event with response callback. |
Server Events
Server-side event listeners run on the server instead of the client. They use the same UIEvents type constants and support both bubble and capture phases. They are automatically synchronized via an internal RPC mechanism.
RPC Events
RPC (Remote Procedure Call) events let the client explicitly invoke logic on the server and optionally receive a response.
// Register an RPC event during element initialization
RPCEmitter emitter = element.addRPCEvent(ele ->
RPCEventBuilder.simple(UIEvents.CLICK, (e, args) -> {
// This runs on the server
ServerPlayer player = e.modularUI.player;
player.sendSystemMessage(Component.literal("Hello from server!"));
})
);
// Trigger the RPC from client (e.g., inside a client event listener)
element.addEventListener(UIEvents.CLICK, event ->
element.sendEvent(emitter.event())
);
Data Bindings
Data bindings automatically synchronize values between server and client. Use addSyncValue in Java, or the bind* DSL helpers in Kotlin.
Rendering
| Method | Signature | Description |
|---|---|---|
isDisplayed() |
boolean |
Returns true if display is not NONE. |