Buttons & controls
Player-driven interactions — clickable buttons, toggles and sliders, and pinned HUD widgets.
Where events fire on their own and actions are chosen by the AI, these are chosen by the player. All three live in the scenario's Interactions tab.
Buttons
A button is shown during the chat; pressing it runs its effects — set flags, inject a message, run a script.
Buttons take the same conditions as everything else, so a button appears only when its flag filter passes. A disabled flag filter shows the button greyed out instead of hiding it.
Labels are templates, so a button can display live state:
Bribe the guard ({{ variables.bribe_cost }}g)
{{ if variables.gold >= 50 }}Bribe{{ else }}Too poor{{ end }}List the variables a button reads under Watched variables and it re-renders whenever they change.
From a script
chat.setButtons(key, buttons) registers buttons at runtime. Calling it again with the same key replaces that set; an empty array clears it.
import { chat } from "@voxta";
chat.setButtons('doors', [
{ name: 'Left door', description: 'Open the left door', effect: { setFlags: ['chose_left'] } },
{ name: 'Right door', description: 'Open the right door', effect: { setFlags: ['chose_right'] } },
]);
chat.addEventListener('buttonPressed', (e) => {
console.log(`Pressed ${e.button}`);
});Fields: name, description, flagsFilter, roleFilter, once, disabled, and an effect of setFlags / note / secret / instructions / event / story / trigger / maxTokens / maxSentences.
Runtime buttons cannot carry an inline script. Set a flag, or listen for buttonPressed.
Controls
Controls are stateful player inputs — a toggle, a checkbox, a slider — each bound to a chat variable that holds the value in both directions. The panel is registered from a script:
import { chat } from "@voxta";
chat.setControls('settings', {
title: 'Settings',
controls: [
{ type: 'toggle', variable: 'lights_on', label: 'Lights' },
{ type: 'checkbox', variable: 'safe_mode', label: 'Safe mode' },
{ type: 'slider', variable: 'volume', label: 'Volume', min: 0, max: 100, step: 5, live: true },
],
});
chat.addEventListener('controlChanged', (e) => {
chat.note(`${e.variable} is now ${e.value}`);
});| Field | Notes |
|---|---|
type | toggle, checkbox or slider. |
variable | Required. The chat variable it reads and writes. |
label | Defaults to the variable name. |
flagsFilter, disabled | Conditions. |
min, max, step | Sliders only. min must be below max. |
live | Sliders only — send throttled updates while dragging, not just on release. |
Because controls write chat variables, everything else can read them with a $variable condition.
HUD widgets
Pinned stat widgets — health, mana, a clock — placed on the stage at authored positions. They are created in the editor (Interactions → HUD), each watching one chat variable. There is no script call; move the bar by setting the variable:
chat.set('hp', Math.max(0, chat.get('hp', 100) - 10));Label, icon, color, min/max and position all live on the widget. Variables persist with the chat, so a widget survives resume on its own. Gate it with a flag filter like any button.
For the richer scripted HUD — inventories, checklists, shop windows — see HUD & stage effects.