Violet

Menu

On this page

The core.ui module lets scripts build their own settings UI in the web menu. Every constructor takes a single options table and returns an element handle you can read, write, and mutate at runtime. Settings persist across sessions and are also reachable through core.get_setting() / core.set_setting().

lua
local enabled = core.ui.checkbox{ id = "enabled", label = "Enable", panel = "General", default = false }

function on_tick()
  if enabled:get() then
    -- ...
  end
end
IDs, tabs & sandboxing
  • IDs are namespaced per script as lua.<script>.<id> (e.g. id = "enabled" in my_script.lua becomes lua.my_script.enabled). An ID you pass that already starts with lua. is kept as-is. This keeps scripts from colliding with each other or with core settings. Prefer the handle (elem:get()) so you never have to type the full ID; if you use core.get_setting, pass the full namespaced ID.
  • Custom tabs are allowed. Omit tab to land in the shared Lua tab, or pass any name to create your own top-level tab. Reserved/core tab names (autos, combat, hacks, items, map, macros, keybinds, packets, debug, settings) are rejected.
  • Idempotent. Re-running a constructor with an existing ID returns a handle to the existing element instead of creating a duplicate, so it's safe to build your UI at the top of the script.

Common options

Every constructor accepts these keys in its options table:

KeyTypeNotes
idstringRequired. Namespaced to lua.<script>.<id>.
labelstringDisplay label.
panelstringRequired. Section within the tab.
tabstringTop-level tab. Defaults to "Lua".
tooltipstringHover text.
orderintSort order within the panel (lower first).
descriptionstringPanel subtitle (card description).
visible_whenstringID of another element; this one is hidden unless that element is truthy. Namespaced like id.
hiddenboolStart hidden (toggle later with :set_visible).
disabledboolStart non-interactive (toggle later with :set_enabled).
dangerousboolHidden unless "Show Dangerous" is on.
transientboolNever saved to profiles (runtime-only).
criticalbool | stringMark safety-critical; a string overrides the alert label.

Creating widgets

core.ui.checkbox(opts) -> element

Boolean toggle. Extra option: default (bool).

lua
local cb = core.ui.checkbox{ id = "enabled", label = "Enable", panel = "General", default = false }

core.ui.slider_int(opts) -> element

Integer slider. Extra options: default, min, max, step (defaults: 0 / 0 / 100 / 1).

lua
local spd = core.ui.slider_int{ id = "speed", label = "Speed", panel = "General",
                                default = 50, min = 0, max = 100, step = 5 }

core.ui.slider_float(opts) -> element

Float slider. Extra options: default, min, max, step, rounding (defaults: 0 / 0 / 1 / 0.1 / 2 decimals).

lua
local r = core.ui.slider_float{ id = "ratio", label = "Ratio", panel = "General",
                                default = 1.0, min = 0.0, max = 5.0, step = 0.1, rounding = 2 }

core.ui.dropdown(opts) -> element

Single-select dropdown. Extra options: options (array of strings), default (0-based index). Its value is the selected index.

lua
local target = core.ui.dropdown{ id = "target", label = "Target", panel = "Targeting",
                                 options = { "Closest", "Random" }, default = 0 }

core.ui.radio_group(opts) -> element

Like a dropdown but rendered as a row of buttons. Extra options: options, default (index). Value is the selected index.

lua
local mode = core.ui.radio_group{ id = "mode", label = "Mode", panel = "General",
                                  options = { "Safe", "Fast", "YOLO" }, default = 0 }

core.ui.multi_select(opts) -> element

Listbox where several options can be checked. Extra options: options, default (array of indices). Value is a sorted array of selected indices.

lua
local kinds = core.ui.multi_select{ id = "kinds", label = "Hit Kinds", panel = "Targeting",
                                    options = { "Mobs", "Reactors", "NPCs" }, default = { 0 } }

core.ui.input_text(opts) -> element

Text field. Extra options: default (string), flags (array of strings, passed to the renderer).

lua
local note = core.ui.input_text{ id = "note", label = "Note", panel = "General", default = "" }

core.ui.keybind(opts) -> element

Key capture. Extra option: default (key name string, e.g. "F8").

lua
local key = core.ui.keybind{ id = "toggle_key", label = "Toggle Key", panel = "General", default = "F8" }

core.ui.color(opts) -> element

RGBA color picker. Extra option: default (array of 4 floats { r, g, b, a }, each 0–1).

lua
local col = core.ui.color{ id = "tint", label = "Tint", panel = "General", default = { 1, 0, 0, 1 } }

core.ui.button(opts) -> element

One-shot action button — no value; poll it with :pressed() (see Buttons). Extra options: variant ("default", "destructive", "outline", "secondary", "ghost"), confirm (confirmation prompt shown before firing).

lua
local run = core.ui.button{ id = "run", label = "Delete", panel = "Actions", variant = "destructive", confirm = "Are you sure?" }

core.ui.static_text(opts) -> element

Display-only text (no value). Extra options: text (the content), style ("muted", "body", or "heading"), markdown (when true, render inline **bold**, *italic*, `code`). Update it later with :set_text().

lua
local status = core.ui.static_text{ id = "status", panel = "Actions", style = "body", text = "idle" }

core.ui.progress(opts) -> element

Read-only progress bar. Extra options: value, min, max (defaults 0 / 0 / 1), display ("percent" or "value"), color ("violet", "success", "warning", "danger", "info"). Drive it from script with :set_value().

lua
local bar = core.ui.progress{ id = "bar", label = "Progress", panel = "Actions", value = 0, min = 0, max = 100, color = "success" }

core.ui.separator(opts) -> element

Visual divider. With a label it renders as a small section heading; without one, a plain rule.

lua
core.ui.separator{ id = "sec1", label = "Advanced", panel = "General" }

The element handle

Every constructor returns a handle. Methods re-resolve the element each call, so a handle stays safe even if the element is later removed (calls become no-ops). Mutator methods return the handle, so they can be chained.

element:get() -> any

Returns the current value (bool / number / string / array, depending on widget type).

lua
if cb:get() then core.log("on") end

element:set(value) -> boolean

Sets the value, coerced to the element's type, and pushes it to the web menu.

lua
spd:set(75)

element:id() -> string

Returns the full namespaced ID (e.g. lua.my_script.enabled).


element:set_label(label) -> element

Changes the display label at runtime.


element:set_tooltip(text) -> element

Changes the tooltip at runtime.


element:set_visible(visible) -> element

Shows or hides the element. Hidden elements are removed from the layout.

lua
spd:set_visible(mode:get_index() ~= 2)

element:visible() -> boolean

Returns whether the element is currently visible.


element:set_enabled(enabled) -> element

Enables or disables interaction (the element stays visible but greys out).


element:enabled() -> boolean

Returns whether the element is currently enabled.


element:set_visible_when(other_id) -> element

Binds conditional visibility to another element's value at runtime.


element:set_order(order) -> element

Changes the sort order within the panel.


element:set_panel(panel) -> element

Moves the element to a different panel.


element:set_options(options) -> element

Replaces the option list of a dropdown, radio_group, or multi_select at runtime. The selected index is clamped to the new range.

lua
target:set_options({ "Closest", "Random", "Boss", "Elite" })

element:get_index() -> number

Returns the selected index of a dropdown or radio_group.


element:set_index(index) -> element

Sets the selected index of a dropdown or radio_group.


element:get_selected() -> any

For dropdown/radio_group returns the selected option string; for multi_select returns the array of selected indices.


element:set_selected(indices) -> element

Sets the selected indices of a multi_select (array of indices).


element:set_min(value) -> element

Changes a slider's minimum at runtime (value is re-clamped).


element:set_max(value) -> element

Changes a slider's maximum at runtime (value is re-clamped).


element:set_step(value) -> element

Changes a slider's step at runtime.


element:set_text(text) -> element

Changes the text of a static_text element.


element:set_value(value) -> element

Sets the current value of a progress bar.


element:pressed() -> boolean

For a button: returns true exactly once after each click, then clears. Poll it in on_tick.


element:remove()

Removes the element from the menu.

Buttons

There is no UI event callback system; buttons are polled. :pressed() returns true once per click and then resets, so check it inside on_tick:

lua
local run = core.ui.button{ id = "run", label = "Run Once", panel = "Actions" }

function on_tick()
  if run:pressed() then
    core.log("button clicked")
  end
end

Widget reference

ConstructorValue (:get())Extra optionsKey methods
checkboxbooldefault:get :set
slider_intnumberdefault min max step:get :set :set_min :set_max :set_step
slider_floatnumberdefault min max step roundingsame as slider_int
dropdownindexoptions default:get_index :set_index :get_selected :set_options
radio_groupindexoptions defaultsame as dropdown
multi_selectindex arrayoptions default:get_selected :set_selected :set_options
input_textstringdefault flags:get :set
keybindstringdefault:get :set
color{r,g,b,a}default:get :set
buttonvariant confirm:pressed
static_texttext style markdown:set_text
progressnumbervalue min max display color:set_value
separator

Full example

lua
plugin = {
    name = "UI Demo",
    version = "1.0.0",
    author = "Author",
    description = "Showcases the core.ui API",
    load = true
}

local TAB = "UI Demo"

local enabled = core.ui.checkbox{ id = "enabled", label = "Enable", tab = TAB, panel = "General", default = true }
local mode    = core.ui.radio_group{ id = "mode", label = "Mode", tab = TAB, panel = "General",
                                     options = { "Safe", "Fast", "YOLO" }, default = 0 }
local speed   = core.ui.slider_int{ id = "speed", label = "Speed", tab = TAB, panel = "General",
                                    default = 50, min = 0, max = 100, step = 5 }
local target  = core.ui.dropdown{ id = "target", label = "Target", tab = TAB, panel = "Targeting",
                                  options = { "Closest", "Random" }, default = 0 }
local status  = core.ui.static_text{ id = "status", tab = TAB, panel = "Actions", style = "body", text = "idle" }
local bar     = core.ui.progress{ id = "bar", label = "Progress", tab = TAB, panel = "Actions", value = 0, min = 0, max = 100 }
local run     = core.ui.button{ id = "run", label = "Run Once", tab = TAB, panel = "Actions" }

local running, ticks = false, 0

function on_tick()
    if run:pressed() and enabled:get() then
        running, ticks = true, 0
        status:set_text("running (mode=" .. mode:get_selected() .. ", target=" .. target:get_selected() .. ")")
        target:set_options({ "Closest", "Random", "Boss", "Elite" })  -- grow the list at runtime
    end

    if running then
        ticks = ticks + 1
        bar:set_value(math.min(ticks, 100))
        if ticks >= 100 then
            running = false
            status:set_text("done")
        end
    end

    speed:set_visible(mode:get_index() ~= 2)  -- hide Speed in YOLO mode
end

Legacy: core.menu

The original core.menu functions still work — they are thin wrappers over core.ui that force the Lua tab and the legacy lua.<id> naming (no per-script segment). They return a boolean instead of a handle, so to read/write their values you use core.get_setting / core.set_setting with the full lua.<id> path. Prefer core.ui for new scripts.

core.menu.create_checkbox(id, label, tab, panel, default_value [, tooltip]) -> boolean

Creates a checkbox setting (the tab argument is ignored — always "Lua").

lua
core.menu.create_checkbox("myScript.enabled", "Enable Feature", "Lua", "My Script", false)
-- Registered as id="lua.myScript.enabled"; read with core.get_setting("lua.myScript.enabled")

core.menu.create_slider_int(id, label, tab, panel, default, min, max [, step [, tooltip]]) -> boolean

Creates an integer slider setting. step defaults to 1.


core.menu.create_slider_float(id, label, tab, panel, default, min, max [, step [, tooltip [, rounding]]]) -> boolean

Creates a float slider setting. step defaults to 0.1, rounding defaults to 2.


core.menu.create_dropdown(id, label, tab, panel, options, default_index [, tooltip]) -> boolean

Creates a dropdown setting. options is a Lua array of strings; default_index is 0-based.


core.menu.create_keybind(id, label, tab, panel [, default_key [, tooltip]]) -> boolean

Creates a keybind setting.


core.menu.create_input_text(id, label, tab, panel [, default_value [, tooltip]]) -> boolean

Creates a text input setting.