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 isbox. - 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; mixesrounded. - 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>.
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
| Name | Type | Description |
|---|---|---|
value | boolean | Value of the switch (default: false). |
disabled | boolean | Whether the switch is disabled (default: false). |
Emits
ui-switch-changed— the switch was toggled.event.detailis the newbooleanvalue.
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
| Name | Type | Description |
|---|---|---|
type | 'box' | 'circle' | 'cube' | 'dodecahedron' | 'line' | 'pyramid' | Type of layout (default: box). |
radius | number | Radius for circle, cube, dodecahedron and pyramid (default: 1). |
angle | number | Angle between items for circle, 0–360 (default: 0). |
columns | number | Number of columns for box (default: 1). |
margin-column | number | Spacing between columns for box (default: 1). |
margin-row | number | Spacing between rows for box (default: 1). |
order-attribute | string | Attribute used to order the children. |
plane | string | Plane the layout lies in, e.g. xy (default), xz, yz. |
reverse | boolean | Reverse the order of the children (default: false). |
fill | boolean | For 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
| Name | Type | Description |
|---|---|---|
value | number | Start value, 0 to 1 (default: 0). |
width | number | Width of the slider rail (default: 0.4). |
height | number | Height of the slider rail (default: 0.05). |
rail-radius | number | Corner radius of the rail (default: 0.025). |
handle-radius | number | Radius of the slider handle (default: 0.025). |
Emits
valuechange— the handle moved.event.detailis the new value (0to1).
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
| Name | Type | Description |
|---|---|---|
icon | string | Icon name from Google Material Symbols Rounded, e.g. home, play_arrow, close (default: close). |
color | string | Color of the icon (default: white). |
size | number | Size 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
| Name | Type | Description |
|---|---|---|
height | number | Height of the card (default: 0.2). |
width | number | Width of the card (default: 0.5). |
color | string | Color of the card (default: white). |
radius | number | Radius of the card corners (default: 0.02). |
opacity | number | Opacity of the card (default: 0.6). |
border-color | string | Color of the card border (default: lightgray). |
border-width | number | Width of the card border (default: 0.0075). Set 0 for no border. |
border-opacity | number | Opacity of the card border (default: 1). |
render-order | number | Render 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
| Name | Type | Description |
|---|---|---|
width | number | Width of the panel (default: 5). |
height | number | Height of the panel (default: 1). |
depth | number | Thickness (default: 1). Use 0.001 for a thin panel. |
border-radius (or radius) | number | Corner radius (default: 0.25). |
border-width | number | Width of the rim (default: 0.01). |
color | string | Face color (default: white). |
border-color | string | Rim color (default: #c33664). |
opacity | number | Face opacity (default: 0.9). Use 1 for a solid panel. |
curve-segments | number | Segments per rounded corner (default: 32). |
env-map-intensity | number | Strength of environment reflections (default: 1). |
tone-mapped | boolean | Whether the panel is tone-mapped (default: false). |
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
| Name | Type | Description |
|---|---|---|
align | string | Alignment of the text (left, center, right). |
anchor | string | Anchor point of the text. |
baseline | string | Baseline alignment of the text. |
clip-rect | string | Clip rectangle of the text. |
color | string | Color of the text (default: white). |
depth-offset | number | Depth offset of the text. |
fill-opacity | number | Opacity of the glyphs, 0–1 (for fades). |
font | string | Font of the text. |
font-size | number | Font size of the text, in metres. |
letter-spacing | number | Letter spacing of the text. |
line-height | number | Line height of the text. |
max-width | number | Maximum line width before wrapping. |
outline-color | string | Outline color of the text. |
outline-width | number | Outline width of the text. |
overflow-wrap | string | Overflow wrap of the text. |
render-order | number | Render order of the text. |
side | string | Side of the text. |
style-ranges | string | Rich text: JSON keyed by the character index in value where a style starts, each entry { color, size, font, valign }. |
tone-mapped | boolean | Whether the text is tone-mapped (default: false). |
value | string | Value of the text. |
white-space | string | White space handling of the text. |
y-offset | number | Y offset of the text. |
z-offset | number | Z 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
| Name | Type | Description |
|---|---|---|
height | number | Height of the button (default: 0.1). |
width | number | Width of the button (default: 0.4). |
color | string | Color of the button (default: white). |
radius | number | Radius of the button corners (default: 0.05). |
disabled | boolean | Whether the button is disabled. A disabled button is dimmed and loses its ui class, so it gets no pointer events. |
tooltip-text | string | Tooltip 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
| Name | Type | Description |
|---|---|---|
color | string | Color of the line (default: #000). |
width | number | Line thickness. The value × 1000 is the width in screen pixels (default: 0.001, 1 px). |
start | string | Starting point of the line, x y z (default: 0 0 0). |
end | string | Ending 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
| Name | Type | Description |
|---|---|---|
depth | number | Depth of the box (default: 0.025). |
height | number | Height of the box (default: 0.5). |
width | number | Width of the box (default: 0.75). |
color | string | Color of the box (default: #ff0000). |
transparent | boolean | Whether the box is transparent (default: true). |
opacity | number | Opacity of the box (default: 0.8). |
radius | number | Radius of the rounded edges (default: 0.2). |
curve-segments | number | Segments 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 oflocal-trigger).beginCollide— a contact with the trigger begins (respectslocal-trigger).endCollide— a contact with the trigger ends (respectslocal-trigger).
Properties
| Name | Type | Description |
|---|---|---|
geometry | Object | A-Frame geometry settings that give the trigger its shape. |
body | Object | Physics body settings (default: type: static; isTrigger: true). |
local-trigger | boolean | Ignore contacts with the physics bodies of other (remote) players (default: true). |
visible | boolean | Debug: 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
| Name | Type | Description |
|---|---|---|
src | string | URL of a glTF/GLB file, or #id of an <a-asset-item>. |
env-map-intensity | number | Intensity of the environment map. |
cast-shadow | boolean | Whether the model casts shadows. |
receive-shadow | boolean | Whether 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
| Name | Type | Description |
|---|---|---|
src | string | URL of the video file. |
width | number | Width of the screen (default: 3). |
height | number | Height of the screen (default: 1). |
radius | number | Corner radius of the screen (default: 0). |
distance-model | string | Positional audio distance model: linear, inverse, exponential (default). |
max-distance | number | Maximum audio distance (default: 212). |
ref-distance | number | Reference audio distance (default: 15). |
rolloff-factor | number | Audio rolloff factor (default: 10). |
cone-inner-angle | number | Inner angle of the audio cone (default: 190). |
cone-outer-angle | number | Outer angle of the audio cone (default: 180). |
cone-outer-gain | number | Gain outside the audio cone (default: 0.01). |
player-debug | boolean | Show 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,videoEndedvideoTimeUpdate—event.detailis{ currentTime, duration }.videoLoadedMetadata—event.detailis{ 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>