Installation
To enable the ox_lib library inside of your resource, add @ox_lib/init.lua as a shared_script in your fxmanifest.lua file:
fx_version 'cerulean'
game 'rdr3'
shared_scripts {
'@ox_lib/init.lua',
}
Make sure ox_lib is started before any resources that depend on it in your server.cfg!
Building the UI
For advanced UI building with ox_lib, please visit the official documentation:
Context menus provide an intuitive way to display multiple options to players.
Use lib.registerContext to define a menu’s structure:
lib.registerContext({
id = 'example_menu',
title = 'Example Menu',
options = {
{
title = 'Open Inventory',
description = 'View your inventory items.',
icon = 'fa-solid fa-box',
iconColor = '#C53030',
event = 'inventory:client:open',
arrow = true
},
{
title = 'Toggle Duty',
description = 'Clock in or out of duty',
icon = 'fa-solid fa-shield',
iconColor = '#48BB78',
event = 'job:client:toggleDuty',
arrow = true
},
{
title = 'Check Money',
description = 'View your current balance',
icon = 'fa-solid fa-dollar-sign',
iconColor = '#F6E05E',
onSelect = function()
local PlayerData = RSGCore.Functions.GetPlayerData()
local cash = PlayerData.money.cash
lib.notify({
title = 'Bank Balance',
description = 'You have $'..cash,
type = 'success'
})
end
},
{
title = 'Open Sub Menu',
description = 'Navigate to another menu',
icon = 'fa-solid fa-arrow-right',
menu = 'sub_menu_id', -- Opens another registered menu
arrow = true
}
}
})
- title
string - The display text for the option
- description
string (optional) - Additional information shown below the title
- icon
string (optional) - Font Awesome icon class (e.g., 'fa-solid fa-box')
- iconColor
string (optional) - Hex color for the icon (e.g., '#C53030')
- event
string (optional) - Client event to trigger when selected
- serverEvent
string (optional) - Server event to trigger when selected
- onSelect
function (optional) - Function to execute when selected
- args
any (optional) - Arguments to pass to the event/function
- arrow
boolean (optional) - Shows an arrow indicator
- menu
string (optional) - ID of another menu to open
- disabled
boolean (optional) - Greys out and disables the option
- metadata
table (optional) - Additional data displayed on the right side
Display a registered menu using lib.showContext:
lib.showContext('example_menu')
Complete Example
-- Register main menu
lib.registerContext({
id = 'police_menu',
title = 'Law Enforcement Menu',
options = {
{
title = 'Check ID',
description = 'View citizen identification',
icon = 'fa-solid fa-id-card',
event = 'police:client:checkId',
arrow = true
},
{
title = 'Search Player',
description = 'Search nearby citizen',
icon = 'fa-solid fa-magnifying-glass',
event = 'police:client:searchPlayer',
arrow = true
},
{
title = 'Jail Options',
description = 'Access jail system',
icon = 'fa-solid fa-handcuffs',
menu = 'jail_submenu',
arrow = true
}
}
})
-- Register sub-menu
lib.registerContext({
id = 'jail_submenu',
title = 'Jail Menu',
menu = 'police_menu', -- Back button returns to this menu
options = {
{
title = 'Send to Jail',
icon = 'fa-solid fa-lock',
serverEvent = 'police:server:jailPlayer',
args = { time = 300 }
},
{
title = 'Release from Jail',
icon = 'fa-solid fa-unlock',
serverEvent = 'police:server:releasePlayer'
}
}
})
-- Show the menu
lib.showContext('police_menu')
Notifications
Custom notifications with extensive styling options.
Client-Side Notifications
lib.notify({
title = 'Success!',
description = 'You have received $500',
type = 'success',
icon = 'fa-solid fa-dollar-sign',
iconColor = '#48BB78',
duration = 5000,
position = 'top-right'
})
Server-Side Notifications
TriggerClientEvent('ox_lib:notify', source, {
title = 'Error!',
description = 'You do not have permission',
type = 'error',
icon = 'fa-solid fa-triangle-exclamation',
iconAnimation = 'shake',
duration = 7000
})
Notification Properties
- title
string (optional) - The notification title
- description
string - The main notification message
- type
string - Type of notification: 'success', 'error', 'warning', 'info'
- icon
string (optional) - Font Awesome icon class
- iconColor
string (optional) - Hex color for the icon
- iconAnimation
string (optional) - Animation: 'spin', 'shake', 'beat', 'fade', 'bounce'
- duration
number (optional) - Duration in milliseconds (default: 5000)
- position
string (optional) - Position: 'top', 'top-right', 'top-left', 'bottom', 'bottom-right', 'bottom-left', 'center-right', 'center-left'
Notification Types Examples
-- Success
lib.notify({
title = 'Item Purchased',
description = 'You bought a canteen for $15',
type = 'success'
})
-- Error
lib.notify({
title = 'Purchase Failed',
description = 'Not enough money',
type = 'error'
})
-- Warning
lib.notify({
title = 'Low Hunger',
description = 'Your hunger is getting low',
type = 'warning'
})
-- Info
lib.notify({
title = 'Server Restart',
description = 'Server will restart in 10 minutes',
type = 'info'
})
Request user input with customizable forms.
local input = lib.inputDialog('Horse Name', {
{ type = 'input', label = 'Horse Name', description = 'Enter a name for your horse', required = true, min = 3, max = 20 }
})
if input then
local horseName = input[1]
print('Horse named: ' .. horseName)
end
local input = lib.inputDialog('Player Report', {
{
type = 'input',
label = 'Player ID',
description = 'Enter the player server ID',
required = true,
icon = 'fa-solid fa-hashtag'
},
{
type = 'select',
label = 'Report Type',
description = 'Select the type of report',
required = true,
options = {
{ value = 'rdm', label = 'Random Deathmatch' },
{ value = 'vdm', label = 'Vehicle Deathmatch' },
{ value = 'exploit', label = 'Exploiting' },
{ value = 'other', label = 'Other' }
},
icon = 'fa-solid fa-list'
},
{
type = 'textarea',
label = 'Description',
description = 'Describe what happened',
required = true,
min = 10,
max = 500,
icon = 'fa-solid fa-pen'
},
})
if input then
local playerId = input[1]
local reportType = input[2]
local description = input[3]
TriggerServerEvent('admin:server:createReport', playerId, reportType, description)
end
Text Input:
{ type = 'input', label = 'Name', placeholder = 'John Doe', required = true, min = 3, max = 50 }
Number Input:
{ type = 'number', label = 'Amount', placeholder = '100', required = true, min = 1, max = 1000 }
Select Dropdown:
{
type = 'select',
label = 'Choose Option',
options = {
{ value = 'option1', label = 'Option 1' },
{ value = 'option2', label = 'Option 2' }
}
}
Multi-Select:
{
type = 'multi-select',
label = 'Select Multiple',
options = {
{ value = 'opt1', label = 'Option 1' },
{ value = 'opt2', label = 'Option 2' },
{ value = 'opt3', label = 'Option 3' }
}
}
Checkbox:
{ type = 'checkbox', label = 'Accept Terms', required = true }
Textarea:
{ type = 'textarea', label = 'Long Description', min = 10, max = 500 }
Date Picker:
{ type = 'date', label = 'Birth Date', format = 'DD/MM/YYYY' }
Time Picker:
{ type = 'time', label = 'Meeting Time', format = '24' }
Progress Bars
Display progress for actions.
Basic Progress Bar
if lib.progressBar({
duration = 5000,
label = 'Cooking meal...',
useWhileDead = false,
canCancel = true,
disable = {
move = true,
car = true,
combat = true
},
}) then
-- Action completed
lib.notify({ description = 'Meal cooked!', type = 'success' })
else
-- Action cancelled
lib.notify({ description = 'Cooking cancelled', type = 'error' })
end
Progress with Animation
if lib.progressBar({
duration = 3000,
label = 'Fishing...',
useWhileDead = false,
canCancel = true,
disable = {
move = true,
},
anim = {
dict = 'amb_work@world_human_box_pickup@1@male_a@stand_exit_withprop',
clip = 'exit_front'
},
}) then
-- Fishing complete
end
Localization
Text elements support multi-language via locale files.
Setup Localization
- Add to fxmanifest.lua:
ox_lib 'locale'
files {
'locales/*.json',
}
- Create locale files (e.g.,
locales/en.json):
{
"horse_name": "Horse Name",
"horse_desc": "Enter a name for your horse",
"purchase_success": "Purchase successful!",
"not_enough_money": "You don't have enough money"
}
- Use in code:
lib.notify({
title = lib.locale('purchase_success'),
description = lib.locale('not_enough_money'),
type = 'error'
})
Always use locales for multi-language support! Make sure to call lib.locale() at the top of your script if needed.
Alert Dialogs
Simple confirmation dialogs.
local alert = lib.alertDialog({
header = 'Confirm Purchase',
content = 'Are you sure you want to buy this horse for $500?',
centered = true,
cancel = true,
labels = {
confirm = 'Buy',
cancel = 'Cancel'
}
})
if alert == 'confirm' then
-- Player confirmed
TriggerServerEvent('horses:server:buyHorse')
end
Useful Utilities
Request Model
local model = `A_C_Horse_AmericanPaint_Overo`
lib.requestModel(model, 5000) -- 5 second timeout
-- Use model
local horse = CreatePed(model, coords.x, coords.y, coords.z, heading, true, false, false, false)
-- Clean up
SetModelAsNoLongerNeeded(model)
Request Animation Dictionary
lib.requestAnimDict('amb_work@world_human_box_pickup@1@male_a@stand_exit_withprop', 5000)
-- Use animation
TaskPlayAnim(ped, 'amb_work@world_human_box_pickup@1@male_a@stand_exit_withprop', 'exit_front', 8.0, -8.0, -1, 0, 0, false, false, false)
-- Clean up
RemoveAnimDict('amb_work@world_human_box_pickup@1@male_a@stand_exit_withprop')
Best Practices
Use context menus for multiple options: They provide a better UX than command-based systems
Always validate user input: Never trust client-side input on the server without validation
Use locales from the start: It’s easier to add translations early than to retrofit them later
- Request resources once: Don’t request the same model/animation repeatedly
- Clean up resources: Always call
SetModelAsNoLongerNeeded and RemoveAnimDict
- Use progress bars for long actions: Improves player experience
- Cache frequently used data: Don’t query the same data repeatedly
For more advanced features, visit the official ox_lib documentation: https://overextended.dev/ox_lib