Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

selectableList

Luau builder for a single-select listbox composed of focusable per-row canvases inside a panel. Same shape as Z.radioGroup, but rows draw no glyph — they're highlight-on-selection labels — and the wrapping panel declares role="listbox" / row role="option" so screen readers read it as a single-select list.

Exports

  • selectableList(id: string, options: { any }?, selected: number?, opts: SelectableListOpts?) -> any — build a listbox widget. The module returns this function directly.

Types:

  • SelectableListOpts = { style: { [string]: any }?, classes: (string | { string })?, rowWidth: number?, rowHeight: number?, onChange: string?, app: any?, ariaLabel: string?, label: string? }

Usage

local selectableList = require("@builtin::modules.zui.widget.selectableList")
selectableList("category", CATEGORIES, state.cat, {
    onChange = "ui:cat:change",
})

Notes

  • Single-select; selected is a 1-based index. The first call seeds ui.widgetState(id, "selected") from the caller's arg; subsequent ticks read state back from there.
  • Keyboard nav (per-row canvas onKey): ArrowDown / ArrowRight next, ArrowUp / ArrowLeft previous, Home -> 1, End -> #options. Tab walks the per-row canvases via egui's focus chain.
  • For sidebar / asset-browser / category-picker patterns where every option is visible at once. For long lists where only a few items fit, wrap the result in Z.scroll(...).
  • opts.onChange is dispatched as a callback id on the surrounding Z.app router with data.value set to the new 1-based index. Without an app in scope, only ui.widgetState updates.
  • Handlers are registered once per group id (deduped via app._selectableListHandlers); option-count and onChange swaps land without re-registering.