Skip to content

<ui>

<ui> declares an interface: a thing the game can open, holding your components. Its name is the module-scope ref bound to it.

src/shop.ts2
const shopRef = createRef('docs-shop');
export const shopUi = (): UI => (
<ui ref={shopRef} w={252} h={260}>

Declaring one exports an entry point the game — or another interface — opens.

It is returned from a function whose return type is UI.

  • ref: A module-scope createRef(name). The name the ref carries is the interface’s name — what everything outside your code opens it by — and the ref itself is a constant naming the interface’s root, usable wherever a component is. A <ui> with no ref builds and has an id, and nothing outside the build can open it by name.
  • w, h: The root’s size — the same vocabulary a <layer> takes: a number, "fill", a percentage, or { fill: n }. Omit both to fill whatever the interface is opened into. Each must be: a literal, an enum member, a plain const, or a field of a plain object.
  • x, y: Where the interface sits in the slot it is opened into — the same vocabulary as a <layer>’s: a number, "center", "right", "bottom", a percentage, or an anchor with an offset such as { center: 3 }. Defaults to the slot’s top-left corner.
  • children: Whatever the interface shows — any mix of your components, built-in elements, and <layer static> slots.

<ui> takes none of the common props.

  • It must be returned from a function (TS2E301). A bare export const shop = <ui …> is refused.
  • Its size cannot be arithmetic (TS2E301). w={PLATE_W + 20} is refused though PLATE_W alone is allowed; so is a percentage in a named constant.
  • An empty interface is refused (TS2E203). null is not a child here.
  • A fixed-size interface with no x/y lands in the corner. A panel that sizes itself needs x="center" y="center" unless the corner is what you want.
  • { fill: '10%' } is refused here too (TS2E210).
  • Directly inside <ui>, only a <layer> may be static (TS2E302).
refused/ui.ts2
export const bare = ( // not a function
<ui ref={bareRef} w={100} h={100}><Refused /></ui>
);
src/inventory.ts2
const inventoryRef = createRef('docs-inventory');
export const inventoryUi = (): UI => (
<ui ref={inventoryRef} w={196} h={330}>
<Window title="Backpack">

The convention in these pages is a Ui suffix on the function and a Ref suffix on its name: Backpack the component, inventoryUi the interface, inventoryRef the name.

src/integrating.ts2
<ui ref={tradingPostRef} w={252} h={200} x="center" y="center">
src/integrating.ts2
<ui ref={tradingPostRef} w={252} h={200} x="center" y="center">
<TradingPost />
<layer static ref={walletSlot} x={12} y={44} w={88} h={126}>
<Wallet />
</layer>
<layer static ref={offerSlot} x={112} y={44} w={128} h={126} />
</ui>

A slot’s ref is a module-scope createRef, and its name is the slot’s: what a sub-interface opens into and what the server addresses.

src/integrating.ts2
export const isTradingPost = (frame: Int): Boolean => frame === interfaceOf(tradingPostRef);

The ref bound to a <ui> is a constant: interfaceOf(ref) is the interface’s id, and the ref itself can be handed to anything that takes a component.

The compiler says my interface must be returned from a function

Section titled “The compiler says my interface must be returned from a function”

Wrap it:

refused/ui.ts2
export const bare = ( // not a function
<ui ref={bareRef} w={100} h={100}><Refused /></ui>
);
src/hud.ts2
export const hudUi = (): UI => (
<ui ref={hudRef} w={244} h={148}>

My interface is in the top-left corner of the screen

Section titled “My interface is in the top-left corner of the screen”

Add x="center" y="center".

You have omitted w and h, which means “fill the slot”. Give it a size.

Write the number, or a const that is one, not an expression over constants.

Two things in my project have the same name

Section titled “Two things in my project have the same name”

An interface’s wrapper function and the component it hosts tend to get the same name, or names that differ only in case. The compiler refuses both (TS2E128).