Skip to content

Vanilla GUI kit

The vanilla GUI kit is an additive set of widgets and a theme that render in-world screens with classic Minecraft chrome — gray-bevel panels, dark drop-shadow text, inset slots. It exists because the default modern theme (Theme.darkBlue(), flat translucent panels, cyan accents) reads as “too modern” for menu and config surfaces; the vanilla kit gives those screens the look players already know from the options menu.

It’s purely additive: the modern theme, every existing widget, and every screen already shipping are unchanged. You opt in per-screen by picking Theme.vanilla() and using the Vanilla* widgets.

  • You’re building a settings / config / menu screen and want it to look like vanilla Minecraft.
  • You want a slot grid, tab strip, or scrollable list with the classic inset-bevel look.
  • You’re mixing a vanilla-styled sub-panel inside an otherwise modern screen (see themed groups).

Stick with the modern theme for gameplay HUDs and anything where the cyan-accent look fits — the kit doesn’t replace it.

Theme t = Theme.vanilla();

Theme.vanilla() is a preset alongside darkBlue() and amongUs(). It carries the classic container palette (fill #C6C6C6, white light-bevel, #555 dark-bevel, #373737 deep-shadow), dark-gray text, and text scales tuned for menu panels. It also adds three bevel-palette fieldsbevelLight, bevelDark, bevelDeep — that the procedural widgets use. Existing themes get these auto-derived from their panelColor, so they’re unaffected.

All of these are ScreenWidget records you add to a ScreenLayout, or Widgets.* helpers you call against a ScreenContent.Builder.

Widget recordHelperWhat it draws
VanillaPanelWidget(region)vanillaPanelGray panel with a raised bevel (light top/left, dark bottom/right).
VanillaButtonWidget(region, id, label)vanillaButtonClassic button — bevelled fill + centered drop-shadow label.
VanillaSlotWidget(region, textureId, count)vanillaSlotInventory slot — inset bevel, optional item texture + stack count.
VanillaTabWidget(region, id, label, selected)vanillaTabTop tab. Selected tabs invert the bevel (pressed-in) and merge with the panel below.
VanillaScrollListWidget(region, id, rows, firstVisible, visibleCount)vanillaScrollListPaginated row list with up/down arrows.
VanillaFormRow(region, label, buttonId, buttonLabel)vanillaFormRowA label : [button] settings row, split 45% / 50%.
VanillaToggleWidget(region, id, label, value)vanillaTogglelabel : [ON/OFF] — the button’s bevel direction carries the state (no green).
VanillaCycleWidget(region, id, label, displayValue)vanillaCyclelabel : < value > — click advances to the next option.
VanillaStepperWidget(region, id, label, valueText)vanillaStepperlabel : [−] value [+] — minus/plus route to id__dec / id__inc.
VanillaSliderWidget(region, id, label, fraction)vanillaSliderRecessed track + raised handle at fraction (0..1), label centered over it.
ThemedGroupWidget(region, theme, children)Renders its children under a swapped theme.

Label kinds for LabelWidget — drop-shadow text matching vanilla:

  • VANILLA_TITLE, VANILLA_BODY, VANILLA_CAPTION — left-aligned at the region’s x.
  • VANILLA_TITLE_CENTERED — horizontally centered around x (the vanilla menu-title convention).
import me.zlex.conduit.screen.ui.Region;
import me.zlex.conduit.screen.ui.Theme;
import me.zlex.conduit.screen.ui.layout.ScreenLayout;
import me.zlex.conduit.screen.ui.layout.ScreenWidget;
import me.zlex.conduit.screen.ui.layout.ScreenWidget.LabelWidget.Kind;
ScreenContent content = new ScreenLayout(Theme.vanilla(), 0x00000000, List.of(
new ScreenWidget.VanillaPanelWidget(Region.FULL),
new ScreenWidget.LabelWidget(new Region(0.5f, 0.04f, 0f, 0.06f),
"Settings", Kind.VANILLA_TITLE_CENTERED),
new ScreenWidget.VanillaFormRow(new Region(0.06f, 0.20f, 0.88f, 0.07f),
"Difficulty:", "difficulty", "EASY"),
new ScreenWidget.VanillaButtonWidget(new Region(0.32f, 0.88f, 0.36f, 0.06f),
"done", "Done")
)).compile();
ServerScreenManager.showWithId(player, screenId, placement, width, height, content);

Button / form-row / tab / toggle / cycle / stepper clicks route back through ServerScreenManager.onButton(screenId, handler) keyed on the widget’s id, exactly like the modern ActionWidget. The slider routes through ServerScreenManager.onButtonAt(screenId, handler) instead — the positional variant whose handler receives the click’s screen-UV, so you can map it to a 0..1 track fraction. It’s click-to-position, not drag (an in-world screen emits a click, not mouse-move). For most settings menus you won’t wire any of this by hand — VanillaConfigMenu does the routing for every control type, slider included.

The procedural widgets draw bevels from colored quads — perfect at any size and version-proof. There’s also a textured path backed by real vanilla pixel art extracted from the MC jar:

Widgets.vanillaTexturedPanel(b, t, region);
Widgets.vanillaTexturedButton(b, t, region, id, label);
Widgets.vanillaTexturedSlot(b, t, region, contentTextureId, count);

These render 9-slice — corners stay crisp, edges and centre stretch — so textured widgets no longer smear at off aspect ratios. The textured button is a self-contained element with the same white-outline hover as the procedural one, available in the layout DSL as VanillaTexturedButtonWidget. For raw 9-slice of any texture use Widgets.nineSlice(b, region, textureId, srcBorderU, srcBorderV) or the NineSliceWidget record. Corner sizing is resolved client-side (the server compiles the screen before the physical dimensions are known). Textures ship at conduit:textures/gui/vanilla-{panel,button,slot}.png.

ThemedGroupWidget wraps a list of child widgets and renders them under a different theme — so a single screen can mix a modern gameplay HUD with a vanilla-styled settings sub-panel. Nesting is supported.

new ScreenWidget.ThemedGroupWidget(region, Theme.vanilla(), List.of(
new ScreenWidget.VanillaPanelWidget(region),
new ScreenWidget.VanillaButtonWidget(buttonRegion, "ok", "OK")
));
  • Hover + pressed. Buttons brighten their keyline to white on hover (vanilla’s button_highlighted signal); toggles, the selected tab, and active mode buttons use a pressed/inverted-bevel or white-underline state. No green — the lighting carries state.
  • Aspect ratio. UV space isn’t isotropic — a square UV region renders as a rectangle on a non-square panel. For a visually-square slot, scale the height by panelWidth / panelHeight.
  • Available since engine 0.10.0+mc26.1.2.