Skip to content

Dialogs ​

Two modal dialogs that wait for the player: a confirm dialog and a form. Both are client only and block the calling thread until the player answers.

Need more than a confirm or a flat form (tabs, conditional fields, live validation)? Use tm.ui.window instead.

Alert dialog ​

Alert dialogOpen full size
lua
local answer = tm.alertDialog({
    header = tm.locale.t('garage.deleteHeader'),
    content = tm.locale.t('garage.deleteContent'),
    canCancel = true,
    buttons = {
        confirm = { label = tm.locale.t('common.delete'), color = 'error', icon = 'lucide:trash-2' },
        cancel = { label = tm.locale.t('common.keep') },
    },
})

if answer == 'confirm' then deleteVehicle() end

tm.alertDialog(data) returns 'confirm' or 'cancel'. It also returns 'cancel' when the dialog was closed from code, replaced by another dialog, or its resource stopped. tm.closeAlertDialog() closes it from code (the waiting caller gets 'cancel').

FieldMeaning
headerTitle.
contentBody text. Line breaks are kept. It is plain text, not Markdown or HTML.
canCancelShow the cancel button and let Escape cancel. Default true.
overflowScroll long content instead of growing the dialog.
buttons.confirm, buttons.cancelEach takes label, color (any color), icon, iconColor.

Input dialog ​

Input dialog with every row typeOpen full size
lua
local input = tm.inputDialog(tm.locale.t('transfer.title'), {
    { type = 'number', label = tm.locale.t('transfer.amount'), min = 1, required = true, icon = 'lucide:banknote' },
    { type = 'input', label = tm.locale.t('transfer.note'), placeholder = tm.locale.t('transfer.notePlaceholder') },
    { type = 'select', label = tm.locale.t('transfer.account'), options = {
        { value = 'bank', label = tm.locale.t('account.bank') },
        { value = 'cash', label = tm.locale.t('account.cash') },
    }, default = 'bank' },
    { type = 'checkbox', label = tm.locale.t('transfer.notify'), checked = true },
})

if not input then return end            -- cancelled
local amount, note, account, notify = input[1], input[2], input[3], input[4]

tm.inputDialog(heading, rows, options?) returns an array with one entry per row, in row order, or nil when cancelled, closed from code, replaced by another dialog, or its resource stopped. A row left empty (a cleared number, for example) is nil in its slot, so read values by index and do not use #input. tm.closeInputDialog() closes it from code.

A row can be a plain string, which is a text input with that label: tm.inputDialog('Rename', { 'New name' }). The single table form also works: tm.inputDialog({ heading = '...', rows = { ... }, canCancel = false }).

Options ​

FieldMeaning
canCancelShow a cancel button and let Escape close it. Default true (alias allowCancel).
canResetShow a Reset button that restores every default.
icon, iconColorIcon next to the heading.

Row types ​

Every row takes label, description, icon, disabled, required and default. A required row that is empty blocks submit and shows an error under the field. An unknown type becomes a text input.

typeResultExtra fields
input (default)stringplaceholder, password, min and max (character count)
textareastringrows, placeholder. inputarea is an alias.
numbernumbermin, max, step, precision (rounds the result)
selectthe chosen valueoptions, clearable, searchable (on by default above 8 options)
multi-selectarray of chosen valuesthe same as select
checkboxbooleanchecked, requiredMessage
toggleboolean
slidernumbermin, max, step, showValue
color#rrggbb, or #rrggbbaa with alphaalpha adds an opacity slider
datestring
timestring

options entries are { value = ..., label = ..., description = ..., icon = ... } or plain strings. A select option's icon can be a lucide: name, an item:<name> inventory image or an image URL.

Behavior to know about ​

  • Only one alert and one input dialog exist at a time. Opening a second one resolves the first caller with 'cancel' or nil.
  • Dialogs take NUI focus and release it when closed. If another interface widget is still open it keeps focus.
  • The player closes a dialog with Escape (when it can be canceled), the cancel button, or the X. All of them count as cancel.