DataUI Developer Guide & Wiki
Official documentation for the declarative, reactive, and modern user interface framework for Minecraft.
π DataUI Developer Guide & Wiki
Welcome to the official documentation for DataUI, the declarative, reactive, and modern user interface framework for Minecraft (Forge 1.12.2).
Mod version: 1.0.0
π Table of Contents
- Philosophy & Principles
- Quick Start (Creating a Screen)
- Declarative Layout System
- Size Management & Responsive
- Overflow Policy (Overflow & Overlap)
- Reactivity & State Binding (Signals)
- Widget Catalog
- Animations & Transitions
- Themes & Design Tokens
- Debug Mode & Profiler
- Concrete Examples
1. Philosophy & Principles
DataUI is built on four pillars:
- Declarative: You describe what you want to display, not how to manually calculate every X/Y coordinate.
- Reactive: Interfaces subscribe to observable variables (
Signal). A value change updates the component without unnecessarily redrawing the entire screen. - Self-protected yet predictable: By default (
OverflowPolicy.AUTO), DataUI applies visual protection (OpenGL Scissor) without silently distorting your components' geometry. - Zero Garbage Collection during rendering: No object allocations in the main render loop.
2. Quick Start (Creating a Screen)
To create a screen in your mod, extend DataUIScreen and build the node tree in buildUI():
package com.monmod.client.gui;
import com.dataui.api.UI;
import com.dataui.core.Node;
import com.dataui.forge.DataUIScreen;
public class MyMachineScreen extends DataUIScreen {
@Override
protected Node buildUI() {
return UI.stack()
.fillScreen()
.add(
UI.panel()
.width(400)
.height(280)
.centerInParent()
.padding(16)
.add(
UI.column()
.gap(10)
.add(UI.text("Energy Generator").fontSize(14).color(0xFFFFFF))
.add(UI.button("Activate").onClick(() -> System.out.println("Click!")))
)
);
}
}
To open your screen on the client side:
Minecraft.getMinecraft().displayGuiScreen(new MyMachineScreen());
3. Declarative Layout System
DataUI provides several specialized containers accessible via the static UI API:
UI.column()
Stacks children vertically from top to bottom.
UI.column()
.gap(8) // Pixel spacing between each child
.padding(12) // Inner margin
.add(UI.text("Line 1"))
.add(UI.text("Line 2"));
UI.row()
Aligns children horizontally from left to right.
UI.row()
.gap(6)
.add(UI.button("Cancel"))
.add(UI.button("Confirm"));
UI.grid()
Responsive grid with fixed columns or automatic calculation (autoFit).
// Responsive grid: automatically adapts to available width (columns of at least 120px)
UI.grid()
.autoFit(120)
.gap(8)
.add(card1)
.add(card2)
.add(card3);
UI.stack()
Layers children on the same space (layers / z-order).
*Note: Overlap between children is normal and allowed in a Stack.*
UI.stack()
.add(backgroundLayer)
.add(contentLayer)
.add(tooltipLayer);
4. Size Management & Responsive
You can set width (width) and height (height) using the Size utility or numeric values:
| Mode | Example | Description |
|---|---|---|
| Fixed (pixels) | .width(200) or .size(200, 100) | Fixed size in pixels. |
| Fill container | .width(Size.fill()) | Occupies 100% of the available space in the parent. |
| Percentage | .width(Size.percent(50)) | Occupies 50% of the parent's width. |
| Content | .width(Size.content()) | Adjusts exactly to the internal content size. |
Min / Max Constraints
To ensure readability and prevent an element from becoming too small or too large when resizing:
UI.button("Start")
.width(Size.fill())
.minWidth(100) // Will never go below 100px
.maxWidth(250); // Will never exceed 250px
5. Overflow Policy (Overflow & Overlap)
DataUI handles interface overflow cleanly:
UI.panel()
.overflow(OverflowPolicy.AUTO) // Default behavior
Policies (OverflowPolicy)
| Policy | Geometric Effect | Render Effect (Scissor) | Debug Profiler |
|---|---|---|---|
AUTO (Default) | No change | Protected by Scissor on overflow | Warning |
VISIBLE | No change | No scissor (e.g. dropdowns, tooltips) | No warning |
CLIP | No change | Permanent scissor on bounds | No warning |
SCROLL | No change | Used with the Scroll widget | No warning |
SHRINK | Proportionally shrinks flexible children (with minWidth/minHeight floor) | Scissor if still too large | No warning |
WARN | No change | No scissor | Warning |
Overflow vs Overlap
- Layout Overflow: A child physically extends beyond its parent's bounds.
- Node Overlap: Two consecutive children overlap in a
ColumnorRow.
*(In debug mode F9, these two alerts are listed separately.)*
6. Reactivity & State Binding (Signals)
Create state signals to bind your game variables to the interface without manual polling:
// 1. Declare signals
Signal energy = new Signal<>(4500);
Signal status = new Signal<>("Waiting");
// 2. Bind to widgets
UI.text(status) // Text updates automatically
.fontSize(12);
UI.progress(energy) // Gauge animates automatically
.max(10000)
.width(200);
// 3. Change the value anywhere in your code
energy.set(7800);
status.set("Running");
7. Widget Catalog
π² Containers & Cards
UI.panel(): Base panel with background, border, and padding.UI.card(title, subtitle): Modern styled card with header and body.UI.scroll(): Smooth vertical scroll area with mouse wheel.
π Text & Badges
UI.text("Text"): Text display supporting Minecraft formatting (Β§a, etc.) or RGBA colors.UI.badge("STATUS", Color): Small colored pill (e.g. "ONLINE", "WARN", "PRO").
π Controls & Inputs
UI.button("Label"): Button with hover, click, and sound effects.UI.checkbox("Enable option", isChecked): Reactive checkbox.UI.slider(min, max, step, initial): Sliding numeric slider.UI.tabs(): Tab bar to easily switch views.
π Data & Bars
UI.progress(signal): Animated progress bar.UI.itemSlot(itemStack): Interactive Minecraft item slot with native rendering and tooltip.
UI.scroll(): enable scrolling and choose the scrollbar
By default, mouse wheel scrolling and the scrollbar are active. These two options are independent:
// Scrollable content, but hidden scrollbar.
UI.scroll()
.scrollbarVisible(false)
.add(content);
// Fixed area: no mouse wheel scrolling, no scrollbar.
UI.scroll()
.scrollEnabled(false)
.scrollbarVisible(false)
.add(content);
When scrollEnabled(false) is used in a nested scroll, the mouse wheel is passed to the parent container.
8. Animations & Transitions
DataUI includes a smooth animation engine based on easing curves:
// Fade-in and translation appearance animation
UIAnimation.fadeIn(myPanel, 300); // 300 ms
// Custom transition
UIAnimation.tween(node)
.property("alpha", 0.0f, 1.0f)
.property("scale", 0.8f, 1.0f)
.duration(250)
.easing(Easing.EASE_OUT_CUBIC)
.start();
9. Themes & Design Tokens
Customize colors, corner radius, and styles globally:
// Define a modern dark theme
Theme darkTheme = new Theme()
.setBackgroundColor(0xEE1E1E2E)
.setPrimaryColor(0xFF89B4FA)
.setTextColor(0xFFCDD6F4)
.setCornerRadius(6);
DataUI.setTheme(darkTheme);
10. Debug Mode & Profiler
During development, enable debug mode to visualize the component tree, FPS, UI frame time, and warnings in real time:
// In your mod initialization (ClientProxy)
DataUI.debug(true);
Developer Shortcut
- Press F9 in-game to display the Profiling HUD Overlay:
- Performance metrics (Layout time, Render time).
- Live detection of Layout Overflows (elements that overflow).
- Live detection of Node Overlaps (elements that overlap each other).
In production mode (DataUI.debug(false)), all diagnostic calculations are automatically disabled to ensure optimal performance.
11. Concrete Examples
Full example: Industrial machine control screen
Goals achieved:
- Centered, responsive main panel (
Size.percent(90)) - Header with reactive status badge
- Reactive progress bars and gauges
- Auto-adaptive metrics grid (
UI.grid().autoFit(130)) - Scrollable activity log (
UI.scroll()) - 0 manual X/Y calculations, 0 clampToParent() everywhere.
public class MachineScreen extends DataUIScreen {
private final Signal energy = new Signal<>(7200);
private final Signal temperature = new Signal<>(42.5f);
private final Signal active = new Signal<>(true);
private final Signal status = active.map(a -> a ? "Β§aRUNNING" : "Β§cSTOPPED");
@Override
protected Node buildUI() {
return UI.stack()
.fillScreen()
// ββ Background βββββββββββββββββββββββββββββββββββββββββββββββ
.add(
UI.panel()
.fillScreen()
.color(0xFF10131A)
)
// ββ Main Content (90% responsive + Auto-protected) βββββββββββ
.add(
UI.panel()
.width(Size.percent(90))
.height(Size.percent(90))
.centerInParent()
.padding(16)
.overflow(OverflowPolicy.AUTO)
.add(
UI.column()
.gap(12)
// ββ Header ββββββββββββββββββββββββββββββββββ
.add(
UI.row()
.gap(10)
.add(
UI.column()
.gap(2)
.add(UI.text("INDUCTION FURNACE").fontSize(16).color(0xFFFFFFFF))
.add(UI.text("Main factory β’ Level 2").fontSize(10).color(0xFF8A93A6))
)
.add(UI.panel().width(Size.fill()))
.add(UI.badge("β CONNECTED", 0xFF45D483))
)
// ββ Status + Energy βββββββββββββββββββββββββ
.add(
UI.card("Machine status", "Real-time information")
.add(
UI.column()
.gap(8)
.add(
UI.row()
.gap(8)
.add(UI.text("Status").fontSize(11))
.add(UI.text(status).fontSize(11))
)
.add(UI.text("Energy").fontSize(11))
.add(
UI.progress(energy)
.max(10000)
.width(Size.fill())
)
.add(
UI.row()
.gap(6)
.add(UI.text("7 200 / 10 000 FE").fontSize(10).color(0xFF8A93A6))
)
)
)
// ββ Responsive Statistics (Auto-reflow Grid) β
.add(
UI.grid()
.autoFit(130)
.gap(8)
.add(
UI.card("Temperature", "")
.add(UI.text(temperature.map(t -> String.format("%.1f Β°C", t))).fontSize(18))
)
.add(
UI.card("Production", "")
.add(UI.text("1 240 RF/t").fontSize(18))
)
.add(
UI.card("Efficiency", "")
.add(UI.text("94.7 %").fontSize(18))
)
.add(
UI.card("Uptime", "")
.add(UI.text("04:32:18").fontSize(18))
)
)
// ββ Controls + Activity Logs ββββββββββββββββ
.add(
UI.row()
.gap(12)
// Controls
.add(
UI.card("Control", "Machine management")
.width(Size.percent(40))
.add(
UI.column()
.gap(8)
.add(
UI.button("Start")
.width(Size.fill())
.onClick(() -> active.set(true))
)
.add(
UI.button("Stop")
.width(Size.fill())
.onClick(() -> active.set(false))
)
.add(
UI.slider(0, 100, 1, 75)
.width(Size.fill())
)
)
)
// Scrollable log
.add(
UI.card("Log", "Recent events")
.width(Size.fill())
.add(
UI.scroll()
.height(130)
.add(
UI.column()
.gap(5)
.add(UI.text("12:42 Β§aProduction started"))
.add(UI.text("12:43 Β§7Temperature stabilized"))
.add(UI.text("12:45 Β§eHigh energy"))
.add(UI.text("12:47 Β§aNominal production"))
.add(UI.text("12:49 Β§7Automatic maintenance"))
)
)
)
)
)
);
}
}
Rendering and Automatic Responsive Adaptation
With a wide interface:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INDUCTION FURNACE β CONNECTED β
β Main factory β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Machine status β
β RUNNING β
β ββββββββββββββββββββββββββββββββ 7200 / 10000 β
ββββββββββββββ¬βββββββββββββ¬βββββββββββββ¬ββββββββββββββββββββββ€
β Temperatureβ Production β Efficiency β Uptime β
β 42.5 Β°C β 1240 RF/t β 94.7 % β 04:32:18 β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ€
β Control β Log β
β β β
β [ Start ] β 12:42 Production started β
β [ Stop ] β 12:43 Temperature stabilized β
β β 12:45 High energy β
β ββββββββββββββ β ... β
βββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββ
When the window is narrowed, UI.grid().autoFit(130) dynamically reorganizes the cards from 4 columns to 3, then 2, then 1 column, without any additional code.