Skip to content

Elements ​

Every tag AUI understands. The source of truth is Core/Schema/AuiSchema.cs; this page mirrors it.

Attributes every element accepts ​

AttributeTypeMeaning
ididentifiernames the element. Generates E_<ID> (and S_<ID> if clickable). Must be unique in the view (AUI102)
classstringspace-separated class names. May contain bindings: class="card {tone}"
styledeclarationsinline style, prop: value; prop: value. May contain bindings
if{binding}shows or hides the element and frees its space. Starts true
hiddenflaghidden at bake, statically. Never on an element with icon= or key= — see below

hidden breaks icons permanently

A hidden element's subtree is not laid out, at bake time included, and a clickable's icon is positioned by the builder exactly once (the runtime solver never writes an icon's rect). An icon-only button baked hidden therefore has its glyph placed against a zero-wide box and ends up hanging outside the button's left edge, where it stays no matter what is shown or relaid out later. A keyed one collapses to its own padding instead, because TMP measures nothing on an inactive object.

Bake it live and let the binding switch it off on the first frame:

xml
<button onclick="Next" icon="chevron-right" if="{hasNext}"/>

hidden remains correct on a plain panel or text, which the solver owns and re-places.

Structure ​

<view> ​

The root of every .aui file. Exactly one per file (AUI004), and it must be the root (AUI104).

AttributeValuesMeaning
nameidentifierrequired; must equal the file stem (AUI103)
width, heightnumberpanel size in millimetres
shownone, fade, fade-scale, fade-slideenter/leave transition; overrides the show style property
start-hiddenflagthe view starts hidden
iconsnamespreload icons for SetIcon
spritesnamespreload sprites for SetBackground
materialsnamespreload materials for SetMaterial
utilitiesnamespreload star classes for AddClass
pooltag:count ...bake spare elements for CreateElementByTag, e.g. text:16 panel:8
aui
<view name="Chat" width="400" height="300"
      pool="text:8 panel:4" icons="check x" utilities="p-4 opacity-50">
  ...
</view>

The four preload attributes exist because only baked asset references can be swapped in-world.

<panel> and <div> ​

A container. Aliases of each other, and a panel selector matches a div and vice versa. Direction, gap and padding come from the stylesheet; the default is a column.

aui
<panel class="row">
  <text key="a"/>
  <spacer/>
  <button onclick="Go" key="go"/>
</panel>

<spacer> ​

Flexible space. Grows to fill what is left, which is how you push things apart.

AttributeMeaning
sizea fixed gap in mm instead of growing
aui
<spacer/>          <!-- grow: 1 -->
<spacer size="8"/> <!-- a fixed 8 mm gap -->

Content ​

<text> ​

AttributeValuesMeaning
keykeya translation key
text{binding}a runtime string, escaped when set
args{a} {b}bindings filling the key's {placeholder}s, by name
wraptrue, falsewrap onto more lines
max-linesnumbercap the line count of a wrapped text (with ellipsis, the last line ends in ...)
ellipsistrue, falseshow ... when truncated
runtimeflagmeasured and re-measured as runtime text (like text=), for a keyed label you will SetText from code

key, text and literal content are mutually exclusive (AUI115). Literal content is reported as info AUI117, since it will never be translated. A wrap="true" text with no width or max-width wraps at the width its parent gives it.

aui
<text key="shop.title" class="title"/>
<text text="{status}"/>
<text key="shop.owned" args="{count} {itemName}"/>
<text wrap="true" max-lines="3" ellipsis="true" key="shop.blurb" style="max-width: 300"/>
<text>Debug build</text>

<icon> ​

A bundled Lucide icon, tinted by the icon-color style property.

AttributeMeaning
namethe icon file name, without .svg (AUI119 if unknown)
sizesize in mm
aui
<icon name="sliders-horizontal" size="22" class="accent"/>

See icons for the full set.

<image> ​

A sprite asset, by path relative to the .aui.

AttributeValues
srcpath to a sprite asset
modesimple, sliced, fit
aui
<image src="../Art/logo.png" mode="fit"/>

Controls ​

<button> ​

AttributeMeaning
keylabel translation key
iconan icon name shown beside the label
disabled{binding} to grey it out and stop clicks
selected{binding} driving the :selected state
EventSignature
onclickvoid Name()
onhover, onleave, onpress, onreleasevoid Name()

Takes children, so a button can be a whole row.

aui
<button onclick="Buy" key="shop.buy" icon="shopping-cart"/>
<button onclick="Close" icon="x" class="ghost"/>
<button onclick="Buy" key="shop.buy" disabled="{soldOut}"/>
<button onclick="Pick" onhover="Preview" onleave="Unpreview" key="shop.pick"/>

<toggle> ​

A two-state button. With only an icon it is a square; with a key it becomes a labelled switch.

AttributeMeaning
bind{bool}, two-way
keylabel
iconthe "on" mark; hidden while off
disabled{binding}
EventSignature
onchangevoid Name(bool value)
onhover, onleave, onpress, onreleasevoid Name()
aui
<toggle bind="{mute}" icon="check" onchange="MuteChanged"/>
<toggle bind="{mute}" key="audio.mute" onchange="MuteChanged"/>

<slider> ​

AttributeMeaning
bind{float}, two-way
min, maxrange
stepincrement
format-keya key containing {value}, e.g. "{value}%"
decimalsdigits in the formatted value (0 by default)
disabled{binding}
EventSignature
onchangevoid Name(float value)
aui
<slider bind="{volume}" min="0" max="100" step="1"
        format-key="audio.percent" onchange="VolumeChanged"/>

In the theme, background is the track, color the fill and the label, icon-color the handle.

<input> ​

A text box. Clicking parks an invisible target in front of the player; the second click opens VRChat's keyboard. Needs an AUI Input Panel in the scene.

AttributeMeaning
bind{string}, two-way (for a url input: the URL's text, for display)
typetext (default) or url
placeholder-keytranslation key shown while empty
maxlengthcharacter limit; a longer submission is cut to it (text only)
disabled{binding}
EventSignature
onsubmitvoid Name(string value), or void Name(VRCUrl value) when type="url"
aui
<input bind="{nick}" placeholder-key="profile.nickHint" maxlength="24" onsubmit="NickSubmitted"/>
<input type="url" bind="{link}" placeholder-key="profile.linkHint" onsubmit="LinkSubmitted"/>

A url input arms VRChat's own URL field instead of the keyboard field. That matters because Udon cannot build a VRCUrl from a string: the only URL a world can load that was not baked at build time is one a player typed into a VRCUrlInputField. The handler receives that VRCUrl (its text lands in the bound string), and GetInputUrl(E_LINK) returns the last one submitted. The next click reopens the field with it, so the player edits rather than retypes.

csharp
public void LinkSubmitted(VRCUrl value)
{
    VRCStringDownloader.LoadUrl(value, (IUdonEventReceiver)this);
}

<select> and <option> ​

A dropdown. Its options bake as a popup that stays inside the view and always draws above modals.

select attributeMeaning
bind{int} index, two-way
maxbake this many option rows (1..32). The ones past the authored <option>s start inactive and empty, for SetSelectOptionLabel to fill; the popup resizes to the rows that are showing
disabled{binding}
EventSignature
onchangevoid Name(int index)

<option> takes key (or literal text) and must sit directly inside a <select>. The select's value is the option's index; value= is accepted as a name for whoever reads the markup and is not baked or reported. A <select> cannot sit inside a <repeat> (AUI112).

aui
<select bind="{quality}" onchange="QualityChanged">
  <option value="low" key="quality.low"/>
  <option value="medium" key="quality.medium"/>
  <option value="high" key="quality.high"/>
</select>

Filling one at runtime. Labels may be set in any order up to the baked capacity; the count decides how many rows show and resizes the popup.

csharp
SetQualityOptionCount(3);
SetQualityOptionLabel(0, "Low");

<tabs> and <tab> ​

tabs attributeMeaning
bind{int} page index, two-way
forthe id of the pages it drives, when there is more than one group
EventSignature
onchangevoid Name(int page)

<tab> takes page (the id of the page it shows), key and icon, and must sit inside <tabs>.

<pages> and <page> ​

pages attributeValues
modecrossfade, sequential
defaultid of the page shown at start

<page> needs an id and must sit inside <pages>.

aui
<tabs bind="{page}" onchange="PageChanged">
  <tab page="general" key="settings.general" icon="monitor"/>
  <tab page="audio"   key="settings.audio"   icon="headset"/>
</tabs>
<pages id="main" mode="crossfade">
  <page id="general"> ... </page>
  <page id="audio">   ... </page>
</pages>

See pages and tabs.

Lists and creation ​

<repeat> and <empty> ​

Bakes max copies of its single template child.

AttributeMeaning
max1 to 64 (AUI120)
EventSignature
onselectvoid Name(int row)

Exactly one template child plus an optional <empty> (AUI105). <empty> shows when the count is 0.

aui
<repeat id="board" max="5" onselect="Pick">
  <button class="line"><text text="{item.name}"/></button>
  <empty><text key="board.empty" class="hint"/></empty>
</repeat>

See lists.

<template> ​

Bakes max parked copies you link in at runtime with CreateElement. Must be a direct child of <view>.

AttributeMeaning
maxhow many parked copies
poolmark it as a tag pool
slotthe slot id this template serves
viewthe nested view this template holds
aui
<template id="line" max="32">
  <panel class="row"><text text="{item.msg}"/></panel>
</template>

<slot> ​

Bakes parked instances of whole views.

AttributeMeaning
viewsthe view names to park
maxhow many of each
aui
<slot id="cards" views="PlayerCard" max="8"/>
csharp
AuiView card = CreateCardsPlayerCard(E_LOG);

See creating elements.

Composition ​

<component> and <prop> ​

An inline template expanded at compile time, in the same file.

aui
<component name="Stat">
  <prop name="label"/>
  <prop name="value"/>
  <prop name="tone" default="accent"/>
  <panel class="kpi {tone}">
    <text key="{label}" class="hint"/>
    <text text="{value}"/>
  </panel>
</component>

<Stat label="stats.hp" value="{hp}"/>

<prop> takes name, type (string, int, float, bool) and default. It is also valid directly under <view>, where it declares a prop of that view for its host.

<event> ​

Declares an event this view raises. Directly under <view>.

aui
<event name="kicked" type="int"/>
csharp
EmitInt("kicked", Score);

type is the payload type, or absent for none. See components.

Nested views ​

Any other .aui is used by its name as a tag. It takes no children.

aui
<PlayerCard nick="{name}" score="{pts}" on-kicked="PlayerKicked"/>
<AuiLanguagePicker/>

Dialogs ​

A dialog over a dimming backdrop. Directly under <view>; takes no space in the flow.

AttributeMeaning
enabled{bool} that opens and closes it
dismissablefalse to stop a backdrop click closing it
showbody transition: none, fade, fade-scale, fade-slide
EventSignature
onopen, onclosevoid Name()
aui
<modal id="confirm" enabled="{asking}" onclose="ResetCancelled">
  <text key="settings.reset.sure"/>
  <panel class="row">
    <button onclick="DoReset" key="yes" class="primary"/>
    <button onclick="CloseConfirm" key="no"/>
  </panel>
</modal>
auis
modal::backdrop { background: rgba(0, 0, 0, 0.6); }

Where each element may go ​

Most elements go anywhere. These do not (AUI112 otherwise):

ElementMust sit directly inside
optionselect
tabtabs
pagepages
emptyrepeat
propview or component
eventview
componentview
modalview
templateview

Next ​