OverflowOverflow
UI Library

List menu

A keyboard-driven menu pinned to a screen corner. The player moves with the arrow keys, side-scrolls values, ticks checkboxes and confirms, without ever needing the mouse.

A list menu titled "Vehicle settings" with a highlighted row, two side-scroll rows, a checkbox and a fuel bar

registerListMenu

exports.of_ui:registerListMenu(data, cb)
FieldTypeDescription
idstringUnique id. Required.
titlestringHeader text. Required.
optionstable[]The rows. Required.
positionstring?top-left, top-right, bottom-left, bottom-right.
disableInputboolean?Default true: game controls stay disabled while the menu is open. false lets the player keep playing.
canCloseboolean?false removes ESC / Backspace.
onSelectedfunction?(selected, scrollIndex?, args?): fires as the highlight moves.
onSideScrollfunction?(selected, scrollIndex, args?): fires when a value row is scrolled.
onCheckfunction?(selected, checked, args?): fires when a checkbox is toggled.
onClosefunction?(keyPressed?): 'Escape' or 'Backspace'.

cb is the confirm handler: (selected, scrollIndex?, args?).

Every index handed to these callbacks is 1-based, matching the order you declared the options.

showListMenu

exports.of_ui:showListMenu(id, startIndex)
ArgumentTypeDescription
idstringA registered menu.
startIndexnumber?1-based row to start on. Defaults to the first.

hideListMenu

exports.of_ui:hideListMenu(onExit)

Closes the menu. Pass true to also fire its onClose.

setListMenuOptions

exports.of_ui:setListMenuOptions(id, options, index)

Replaces one option when index is given, or all of them when it is not. If that menu is currently open it refreshes in place, so you can rebuild rows while the player is looking at them.

getOpenListMenu

local id = exports.of_ui:getOpenListMenu()

Returns the id of the open menu, or nil.

Options

FieldTypeDescription
labelstringRow label.
descriptionstring?Muted second line.
iconstring?Icon on the left.
iconColorstring?Hex colour for the icon.
progressnumber?0–100 bar under the label.
colorSchemestring?Accent for the progress bar.
valuestable?Makes the row side-scrollable. Entries are strings or { label, description? }.
defaultIndexnumber?1-based starting position of a values row.
checkedboolean?Makes the row a checkbox with this initial state.
argstable?Passed to the callbacks. Never sent to the UI.
closeboolean?false keeps the menu open after confirming this row.

Example

exports.of_ui:registerListMenu({
    id = 'vehicle_settings',
    title = 'Vehicle settings',
    options = {
        { label = 'Engine', icon = 'car', description = 'Toggle the engine', close = false },
        { label = 'Seat', icon = 'chair', values = {
            'Driver', 'Passenger',
            { label = 'Rear left', description = 'Behind the driver' },
            'Rear right',
        } },
        { label = 'Radio', icon = 'radio', defaultIndex = 2, values = {
            'Off', 'Los Santos Rock', 'Non-Stop-Pop',
        } },
        { label = 'Doors locked', icon = 'lock', checked = true },
        { label = 'Fuel', icon = 'gas-pump', progress = 64, colorScheme = '#fdbe22' },
    },
    onSideScroll = function(selected, scrollIndex)
        if selected == 3 then TriggerEvent('radio:setStation', scrollIndex) end
    end,
    onCheck = function(selected, checked)
        if selected == 4 then TriggerEvent('vehicle:setLocked', checked) end
    end,
}, function(selected, scrollIndex)
    print(('confirmed row %d (value %s)'):format(selected, tostring(scrollIndex)))
end)

exports.of_ui:showListMenu('vehicle_settings')

Notes

  • Checkbox state is remembered. Toggling a checkbox updates the registry, so reopening the menu shows the state the player left it in.
  • close = false keeps the menu open after confirming: for rows the player toggles repeatedly.
  • Game input is disabled by default while the menu is open: firing, the weapon wheel and melee are suppressed. Set disableInput = false if your menu should not interrupt play.

On this page