Skip to main content

UI/UX Components

Modules​

Each cap-* primitive maps to an underlying A-Frame component:

  • cap-uix-switch ⇐ ui-switch — Toggle switch (on/off).
  • cap-uix-layout ⇐ layout — Layout container (box/circle/line/etc.). Default type is box.
  • cap-uix-slider ⇐ ui-slider — Select a value from a range.
  • cap-uix-icon ⇐ troika-text — Icon primitive (defaults configured for a close icon).
  • cap-uix-card ⇐ uix-card — Flat rounded rectangle for content.
  • cap-uix-card-box ⇐ card-box — Rounded panel with depth and a coloured rim.
  • cap-uix-text ⇐ troika-text — 3D text in space.
  • cap-uix-button ⇐ ui-btn — Clickable button; mixes rounded.
  • cap-line ⇐ line2 — Draw a line in 3D space.
  • cap-box-rounded ⇐ uix-box-rounded — Rounded box.
  • cap-trigger ⇐ body, trigger — Physics trigger volume.
  • cap-model-loader ⇐ gltf-model-plus — Load & display a glTF model.
  • cap-video-player ⇐ video-player — Video screen with positional audio.

All sizes are in metres. Use these elements inside a script's render() template (see Scripting (JavaScript)) instead of 2D HTML tags such as <button> or <div>.

Making elements clickable

The cursor, VR controllers and hand tracking only hit elements with one of the classes interactable, intersectable, collidable, ui, uihover or navmesh. Write class="ui" on every <cap-uix-*> element you want to click or hover, including the panel behind the buttons.

Pointer events (click, mousedown, mouseenter, mouseleave) do not bubble. A click listener on the script's root entity never sees clicks on a child <cap-uix-button>: bind the handler on the button itself, for example @click=${() => this.onAction()} in the template.


cap-uix-switch ⇐ ui-switch​

A toggle switch that allows the user to choose between two states (typically on/off).

Extends​

  • ui-switch

Properties​

NameTypeDescription
valuebooleanValue of the switch (default: false).
disabledbooleanWhether the switch is disabled (default: false).

Emits​

  • ui-switch-changed — the switch was toggled. event.detail is the new boolean value.

Example​

<cap-uix-switch
class="ui"
value="true"
@ui-switch-changed=${(e) => console.info('switch is now', e.detail)}
></cap-uix-switch>

cap-uix-layout ⇐ layout​

A layout container that arranges its children in a specific layout (box grid, circle, line, etc.). Default type is box.

Extends​

  • layout

Properties​

NameTypeDescription
type'box' | 'circle' | 'cube' | 'dodecahedron' | 'line' | 'pyramid'Type of layout (default: box).
radiusnumberRadius for circle, cube, dodecahedron and pyramid (default: 1).
anglenumberAngle between items for circle, 0–360 (default: 0).
columnsnumberNumber of columns for box (default: 1).
margin-columnnumberSpacing between columns for box (default: 1).
margin-rownumberSpacing between rows for box (default: 1).
order-attributestringAttribute used to order the children.
planestringPlane the layout lies in, e.g. xy (default), xz, yz.
reversebooleanReverse the order of the children (default: false).
fillbooleanFor circle: spread the children over the full circle (default: true).
align'start' | 'center' | 'end'Alignment of the layout (default: end).

Example​

<cap-uix-layout type="circle" radius="1">
<a-entity geometry="primitive: box"></a-entity>
<a-entity geometry="primitive: sphere"></a-entity>
</cap-uix-layout>

cap-uix-slider ⇐ ui-slider​

A slider that allows the user to select a value from a range. The value is a fraction from 0 (left) to 1 (right).

Extends​

  • ui-slider

Properties​

NameTypeDescription
valuenumberStart value, 0 to 1 (default: 0).
widthnumberWidth of the slider rail (default: 0.4).
heightnumberHeight of the slider rail (default: 0.05).
rail-radiusnumberCorner radius of the rail (default: 0.025).
handle-radiusnumberRadius of the slider handle (default: 0.025).

Emits​

  • valuechange — the handle moved. event.detail is the new value (0 to 1).

Example​

<cap-uix-slider
value="0.5"
@valuechange=${(e) => console.info('slider at', e.detail)}
></cap-uix-slider>

cap-uix-icon ⇐ troika-text​

An icon primitive (implemented using troika-text with the Material Symbols Rounded font), with defaults configured for a close icon.

Extends​

  • troika-text

Properties​

NameTypeDescription
iconstringIcon name from Google Material Symbols Rounded, e.g. home, play_arrow, close (default: close).
colorstringColor of the icon (default: white).
sizenumberSize of the icon (default: 0.1).

Example​

<cap-uix-icon icon="home" color="red"></cap-uix-icon>

cap-uix-card ⇐ uix-card​

A flat rectangle with rounded corners and a border, typically used as a lightweight panel. The card faces +Z; use rotation="-90 0 0" to lay it flat on a table.

Extends​

  • uix-card

Properties​

NameTypeDescription
heightnumberHeight of the card (default: 0.2).
widthnumberWidth of the card (default: 0.5).
colorstringColor of the card (default: white).
radiusnumberRadius of the card corners (default: 0.02).
opacitynumberOpacity of the card (default: 0.6).
border-colorstringColor of the card border (default: lightgray).
border-widthnumberWidth of the card border (default: 0.0075). Set 0 for no border.
border-opacitynumberOpacity of the card border (default: 1).
render-ordernumberRender order of the card.

Example​

<cap-uix-card class="ui" width="1" height="0.5" color="#18181b" opacity="0.9">
<cap-uix-text value="Hello World!" align="center" font-size="0.05" position="0 0 0.01"></cap-uix-text>
</cap-uix-card>

cap-uix-card-box ⇐ card-box​

A rounded panel with real depth and a coloured rim. The face points to +Z, like cap-uix-card.

Extends​

  • card-box

Properties​

NameTypeDescription
widthnumberWidth of the panel (default: 5).
heightnumberHeight of the panel (default: 1).
depthnumberThickness (default: 1). Use 0.001 for a thin panel.
border-radius (or radius)numberCorner radius (default: 0.25).
border-widthnumberWidth of the rim (default: 0.01).
colorstringFace color (default: white).
border-colorstringRim color (default: #c33664).
opacitynumberFace opacity (default: 0.9). Use 1 for a solid panel.
curve-segmentsnumberSegments per rounded corner (default: 32).
env-map-intensitynumberStrength of environment reflections (default: 1).
tone-mappedbooleanWhether the panel is tone-mapped (default: false).
Always set width, height and depth

The defaults make a 5 m × 1 m × 1 m block. Set all three on every panel.

Example​

<cap-uix-card-box
class="ui"
width="0.8"
height="0.5"
depth="0.001"
border-radius="0.02"
border-width="0.006"
color="#090e1a"
border-color="#00e5ff"
opacity="1"
>
<cap-uix-text value="STATION HUB" align="center" font-size="0.045" color="#00e5ff" position="0 0.16 0.01"></cap-uix-text>
</cap-uix-card-box>

cap-uix-text ⇐ troika-text​

Displays text in 3D space using troika-text. Sizes are in metres: button labels and body text work well at 0.02–0.035, panel titles at 0.03–0.06.

Extends​

  • troika-text

Properties​

NameTypeDescription
alignstringAlignment of the text (left, center, right).
anchorstringAnchor point of the text.
baselinestringBaseline alignment of the text.
clip-rectstringClip rectangle of the text.
colorstringColor of the text (default: white).
depth-offsetnumberDepth offset of the text.
fill-opacitynumberOpacity of the glyphs, 0–1 (for fades).
fontstringFont of the text.
font-sizenumberFont size of the text, in metres.
letter-spacingnumberLetter spacing of the text.
line-heightnumberLine height of the text.
max-widthnumberMaximum line width before wrapping.
outline-colorstringOutline color of the text.
outline-widthnumberOutline width of the text.
overflow-wrapstringOverflow wrap of the text.
render-ordernumberRender order of the text.
sidestringSide of the text.
style-rangesstringRich text: JSON keyed by the character index in value where a style starts, each entry { color, size, font, valign }.
tone-mappedbooleanWhether the text is tone-mapped (default: false).
valuestringValue of the text.
white-spacestringWhite space handling of the text.
y-offsetnumberY offset of the text.
z-offsetnumberZ offset of the text.

Example​

<cap-uix-text value="Hello World!" color="red" font-size="0.5"></cap-uix-text>

<!-- Two colours in one text: the style starts at character 10 -->
<cap-uix-text value="MAVERICK 1.22x" style-ranges='{"10":{"color":"#33c4ff"}}'></cap-uix-text>

cap-uix-button ⇐ ui-btn​

A clickable button for triggering actions or navigation. Uses ui-btn and mixes rounded. The button has no label of its own: put a <cap-uix-text> or <cap-uix-icon> inside it, slightly in front of the face (position="0 0 0.01").

Extends / Mixes​

  • Extends: ui-btn
  • Mixes: rounded

Properties​

NameTypeDescription
heightnumberHeight of the button (default: 0.1).
widthnumberWidth of the button (default: 0.4).
colorstringColor of the button (default: white).
radiusnumberRadius of the button corners (default: 0.05).
disabledbooleanWhether the button is disabled. A disabled button is dimmed and loses its ui class, so it gets no pointer events.
tooltip-textstringTooltip shown while the pointer is over the button.

Example​

<cap-uix-button
class="ui"
color="red"
width="0.4"
height="0.1"
radius="0.02"
tooltip-text="Starts the round"
@click=${() => this.start()}
>
<cap-uix-text value="Click Me!" align="center" font-size="0.03" position="0 0 0.01"></cap-uix-text>
</cap-uix-button>

cap-line ⇐ line2​

Draws a line in 3D space.

Extends​

  • line2

Properties​

NameTypeDescription
colorstringColor of the line (default: #000).
widthnumberLine thickness. The value × 1000 is the width in screen pixels (default: 0.001, 1 px).
startstringStarting point of the line, x y z (default: 0 0 0).
endstringEnding point of the line, x y z (default: 1 1 1).

Example​

<cap-line start="0 0 0" end="1 1 1" color="red" width="0.003"></cap-line>

cap-box-rounded ⇐ uix-box-rounded​

A box with rounded corners, for pedestals, consoles and slabs.

Extends​

  • uix-box-rounded

Properties​

NameTypeDescription
depthnumberDepth of the box (default: 0.025).
heightnumberHeight of the box (default: 0.5).
widthnumberWidth of the box (default: 0.75).
colorstringColor of the box (default: #ff0000).
transparentbooleanWhether the box is transparent (default: true).
opacitynumberOpacity of the box (default: 0.8).
radiusnumberRadius of the rounded edges (default: 0.2).
curve-segmentsnumberSegments per rounded edge (default: 3). Triangles grow quickly: 1 gives 108, 3 gives 588, 17 gives 14,700.

Colour the box with color: it builds its own mesh and ignores an A-Frame material attribute. For a solid box set opacity="1" transparent="false". Only color changes after the box is created; the other attributes are read once.

Example​

<cap-box-rounded
width="1"
height="1"
depth="1"
color="#27272a"
radius="0.06"
opacity="1"
transparent="false"
></cap-box-rounded>

cap-trigger ⇐ body, trigger​

A physics trigger volume for detecting when something enters or leaves an area. It is a static trigger body (type: static; isTrigger: true) plus the trigger component. Give it a shape with a geometry attribute.

Extends​

  • body, trigger

Emits​

  • collide — on every physics contact (sent by the physics system, regardless of local-trigger).
  • beginCollide — a contact with the trigger begins (respects local-trigger).
  • endCollide — a contact with the trigger ends (respects local-trigger).

Properties​

NameTypeDescription
geometryObjectA-Frame geometry settings that give the trigger its shape.
bodyObjectPhysics body settings (default: type: static; isTrigger: true).
local-triggerbooleanIgnore contacts with the physics bodies of other (remote) players (default: true).
visiblebooleanDebug: show the collider geometry mesh.

Example​

<cap-trigger
visible="false"
local-trigger="true"
@beginCollide=${(e) => {
console.info(e.target)
}}
@endCollide=${(e) => {
console.info(e.target)
}}
geometry="primitive:box;width:8;height:8;depth:8;">
</cap-trigger>

cap-model-loader ⇐ gltf-model-plus​

A model loader for displaying glTF/GLB models, based on gltf-model-plus and shadow.

Extends​

  • gltf-model-plus, shadow

Emits​

  • model-loaded — the model is in the scene (event.detail.model).
  • model-error — the model could not be loaded.

Properties​

NameTypeDescription
srcstringURL of a glTF/GLB file, or #id of an <a-asset-item>.
env-map-intensitynumberIntensity of the environment map.
cast-shadowbooleanWhether the model casts shadows.
receive-shadowbooleanWhether the model receives shadows.

Example​

<cap-model-loader src="https://example.com/model.glb" cast-shadow="true"></cap-model-loader>

cap-video-player ⇐ video-player​

A video screen (a rounded plane) whose sound plays as positional audio from the screen. The video loops and does not start by itself, and there are no built-in on-screen controls: call the component's methods from your script.

Extends​

  • geometry (rounded-plane), video-player

Properties​

NameTypeDescription
srcstringURL of the video file.
widthnumberWidth of the screen (default: 3).
heightnumberHeight of the screen (default: 1).
radiusnumberCorner radius of the screen (default: 0).
distance-modelstringPositional audio distance model: linear, inverse, exponential (default).
max-distancenumberMaximum audio distance (default: 212).
ref-distancenumberReference audio distance (default: 15).
rolloff-factornumberAudio rolloff factor (default: 10).
cone-inner-anglenumberInner angle of the audio cone (default: 190).
cone-outer-anglenumberOuter angle of the audio cone (default: 180).
cone-outer-gainnumberGain outside the audio cone (default: 0.01).
player-debugbooleanShow a helper for the positional audio cone.

Methods​

On el.components['video-player']: playVideo(), pauseVideo(), stopVideo() (pause and rewind), getCurrentTime() and getDuration() (seconds).

Emits​

  • videoPlay, videoPause, videoSeeked, videoEnded
  • videoTimeUpdate — event.detail is { currentTime, duration }.
  • videoLoadedMetadata — event.detail is { duration }.

Example​

<cap-video-player id="screen" src="https://example.com/video.mp4" width="3.2" height="1.8"></cap-video-player>
<cap-uix-button
class="ui"
position="0 -1.1 0.01"
@click=${() => this.el.querySelector('#screen').components['video-player'].playVideo()}
>
<cap-uix-icon icon="play_arrow" position="0 0 0.01"></cap-uix-icon>
</cap-uix-button>