OverflowOverflow
UI Library

Text UI

A prompt pinned to a screen edge, showing what the player can press. Non-blocking: you show it when the player enters a zone and hide it when they leave.

A single-line prompt reading "Open the door" with an E key cap

showText

exports.of_ui:showText(data)
exports.of_ui:showText('Open the door')  -- shorthand: text only
FieldTypeDescription
descriptionstring?The label. text is accepted as an alias.
keysstring?Key cap drawn after description. Together they form one action.
actionstable[]?Full form: several label + key pairs in one prompt. See below.
titlestring?of_ui: heading above the actions. Implies the stack layout.
layoutstring?of_ui: inline (one row, default) or stack (vertical list).
positionstring?right-center, left-center, top-center, bottom-center. Theme decides when omitted.
iconstring|table?Icon before the label.
iconColorstring?Hex colour for the icon.
iconAnimationstring?Font Awesome animation.
styletable?Inline CSS applied to the panel.

Actions

Each entry of actions is one LABEL [KEY] pair:

FieldTypeDescription
labelstringWhat the key does.
keystringKey cap text, e.g. E, G, ESC.
altboolean?Secondary action: a muted key cap instead of the accent one. Use it for cancel.
iconstring|table?Per-row icon, drawn before the label. Best in stack.
iconColorstring?Hex colour for the icon.
iconAnimationstring?Font Awesome animation.

hideText

exports.of_ui:hideText()

Hides the prompt. Safe to call when nothing is showing.

isOpen

local open, text = exports.of_ui:isOpen()

Returns whether a prompt is showing and, if so, its label.

Layouts

One line, one key

exports.of_ui:showText({ text = 'Open the door', keys = 'E' })

With an icon

The same prompt with a wrench icon before the label

exports.of_ui:showText({ text = 'Repair vehicle', keys = 'E', icon = 'wrench' })

Several keys in one row

One row showing "Set point G" and a muted "Cancel ESC"

exports.of_ui:showText({
    actions = {
        { label = 'Set point', key = 'G' },
        { label = 'Cancel', key = 'ESC', alt = true },
    },
})

Stacked, with a heading

A titled panel listing four icon + label + key rows

Give it a title and the prompt becomes a vertical control list, useful when an interaction has more than two or three keys.

exports.of_ui:showText({
    title = 'Heist controls',
    actions = {
        { icon = 'unlock',    label = 'Force the box', key = 'E' },
        { icon = 'door-open', label = 'Open door',     key = 'G' },
        { icon = 'eye',       label = 'Keep watch',    key = 'F' },
        { icon = 'xmark',     label = 'Cancel',        key = 'ESC', alt = true },
    },
})

title sets stack on its own, so you rarely pass layout. Pass layout = 'stack' explicitly if you want the vertical list without a heading, or layout = 'inline' to keep a heading on a single row.

Typical use

Show on enter, hide on exit, and hide it on resource stop too, or the prompt outlives your script:

local shown = false

CreateThread(function()
    while true do
        local coords = GetEntityCoords(cache.ped)
        local near = #(coords - vec3(24.5, -1347.3, 29.5)) < 2.0

        if near and not shown then
            exports.of_ui:showText({ text = 'Rob the register', keys = 'E', icon = 'cash-register' })
            shown = true
        elseif not near and shown then
            exports.of_ui:hideText()
            shown = false
        end

        Wait(250)
    end
end)

AddEventHandler('onResourceStop', function(resource)
    if resource == GetCurrentResourceName() then exports.of_ui:hideText() end
end)

Repeated showText calls with identical content are ignored, so calling it every frame in a loop costs nothing. Changing any label, key or icon does push the update.

On this page