ProgressBar

The progress bar system provides visual feedback for long-running operations with smooth animations. Progress bars automatically animate from 0% to 100% over the specified duration.

Dark Circular Progress
Dark Linear Progress

progress

Display a progress bar with automatic animation and professional styling.

-- Client-side
B2Lib.UI.progress(options)

-- Server-side
B2Lib.UI.progress(playerId, options)

Parameters:

  • playerId (number, server-side only): Player server ID to send the progress bar to

  • options (table): Progress bar configuration options

    • duration (number): Duration in milliseconds for the progress to complete

    • label (string, optional): Text label to display (default: 'Loading...')

    • type (string, optional): Progress type - 'circular' or 'linear' (default: 'circular')

    • position (string, optional): Position on screen (default: from config)

    • showPercentage (boolean, optional): Whether to show percentage text (default: from config)

    • color (string, optional): Progress bar color - hex color or theme color (default: from config)

    • canCancel (boolean, optional): Whether the progress can be cancelled (default: false)

    • cancelKey (string, optional): Key to cancel progress (default: 'X')

    • id (string, optional): Custom progress bar ID (default: auto-generated)

    • size (string, optional): Progress bar size - 'small', 'medium', 'large' (default: 'medium')

    • thickness (number, optional): Progress bar thickness for circular type (default: 8)

    • backgroundColor (string, optional): Background color override

    • textColor (string, optional): Text color override

    • gradient (boolean, optional): Enable gradient effect (default: true)

    • animation (string, optional): Animation style - 'smooth', 'pulse', 'glow' (default: 'smooth')

Returns: number|boolean - Progress bar ID on success, false on failure

Example:

-- Client-side usage
local progressId = B2Lib.UI.progress({
    duration = 5000,
    label = 'Loading player data...',
    type = 'circular',
    showPercentage = true,
    canCancel = true,
    color = '#4CAF50'
})

-- Server-side usage (sends to specific player)
B2Lib.UI.progress(source, {
    duration = 8000,
    label = 'Processing server data...',
    type = 'linear',
    position = 'bottom-center',
    color = '#2196F3',
    showPercentage = true,
    size = 'large'
})

hideProgress

Hide the currently active progress bar immediately.

B2Lib.UI.hideProgress()

Returns: boolean - Success status

Example:

local success = B2Lib.UI.hideProgress()
if success then
    print("Progress bar hidden")
end

getProgressState

Get the current state of active progress bars.

B2Lib.UI.getProgressState()

Returns: table - Progress state information

  • active (boolean): Whether a progress bar is currently active

  • id (string): Current progress bar ID

  • progress (number): Current progress percentage (0-100)

  • duration (number): Total duration in milliseconds

  • elapsed (number): Elapsed time in milliseconds

  • canCancel (boolean): Whether current progress can be cancelled

  • label (string): Current progress label

Example:

local state = B2Lib.UI.getProgressState()
if state.active then
    print(string.format("Progress: %d%% - %s", state.progress, state.label))
end

progressAll (Server-side only)

Send a progress bar to all online players simultaneously.

B2Lib.UI.progressAll(options)

Parameters:

  • options (table): Progress bar configuration options (same as progress function)

Returns: boolean - Success status

Example:

-- Server-side only
B2Lib.UI.progressAll({
    duration = 10000,
    label = 'Server maintenance in progress...',
    type = 'linear',
    position = 'top-center',
    canCancel = false,
    color = '#FF9800'
})

hideProgressPlayer (Server-side only)

Hide progress bar for a specific player from server-side.

B2Lib.UI.hideProgressPlayer(playerId)

Parameters:

  • playerId (number): Player server ID

Returns: boolean - Success status

Example:

-- Server-side only
B2Lib.UI.hideProgressPlayer(playerId)

Progress Types

Circular Progress

Ideal for indeterminate operations and loading states.

-- Client-side
B2Lib.UI.progress({
    duration = 3000,
    label = 'Saving player data...',
    type = 'circular',
    position = 'center',
    showPercentage = true,
    size = 'large',
    color = '#4CAF50'
})

-- Server-side
B2Lib.UI.progress(playerId, {
    duration = 5000,
    label = 'Server processing...',
    type = 'circular',
    showPercentage = true,
    animation = 'pulse',
    thickness = 12
})

Linear Progress

Perfect for file operations and step-by-step processes.

-- Client-side
B2Lib.UI.progress({
    duration = 10000,
    label = 'Downloading update...',
    type = 'linear',
    position = 'bottom-center',
    canCancel = true,
    cancelKey = 'ESC',
    gradient = true
})

-- Server-side
B2Lib.UI.progress(source, {
    duration = 8000,
    label = 'Uploading to server...',
    type = 'linear',
    color = '#2196F3',
    showPercentage = true,
    size = 'large',
    animation = 'glow'
})

Positioning System

Progress bars support a comprehensive 9-position grid system:

Recommended Positions:

  • 'center' - Screen center (default for circular)

  • 'top-center' - Top center

  • 'bottom-center' - Bottom center (default for linear)

Corner Positions:

  • 'top-left' - Upper left corner

  • 'top-right' - Upper right corner

  • 'bottom-left' - Lower left corner

  • 'bottom-right' - Lower right corner

Side Positions:

  • 'center-left' - Left side center

  • 'center-right' - Right side center

-- Different positioning examples
B2Lib.UI.progress({
    duration = 5000,
    label = 'Processing...',
    position = 'center',
    type = 'circular'
})

B2Lib.UI.progress({
    duration = 8000,
    label = 'Loading assets...',
    position = 'bottom-center',
    type = 'linear'
})

B2Lib.UI.progress({
    duration = 3000,
    label = 'Quick task...',
    position = 'top-right',
    type = 'circular',
    size = 'small'
})

Size and Styling Options

Size Variants

-- Small progress bar
B2Lib.UI.progress({
    duration = 3000,
    label = 'Quick operation',
    size = 'small',
    type = 'circular'
})

-- Medium progress bar (default)
B2Lib.UI.progress({
    duration = 5000,
    label = 'Standard operation',
    size = 'medium',
    type = 'linear'
})

-- Large progress bar
B2Lib.UI.progress({
    duration = 10000,
    label = 'Major operation',
    size = 'large',
    type = 'circular',
    thickness = 16
})

Color Customization

-- Theme colors
B2Lib.UI.progress({
    duration = 5000,
    label = 'Success operation',
    color = 'success',  -- Uses theme success color
    type = 'linear'
})

-- Custom hex colors
B2Lib.UI.progress({
    duration = 7000,
    label = 'Custom styled',
    color = '#8B5CF6',
    backgroundColor = '#1F2937',
    textColor = '#F3F4F6',
    type = 'circular'
})

-- Gradient effects
B2Lib.UI.progress({
    duration = 6000,
    label = 'Gradient progress',
    color = '#FF6B6B',
    gradient = true,
    animation = 'glow',
    type = 'linear'
})

Animation Styles

Smooth Animation (Default)

B2Lib.UI.progress({
    duration = 5000,
    label = 'Smooth progress',
    animation = 'smooth',
    type = 'circular'
})

Pulse Animation

B2Lib.UI.progress({
    duration = 4000,
    label = 'Pulsing progress',
    animation = 'pulse',
    type = 'circular',
    color = '#FF9800'
})

Glow Animation

B2Lib.UI.progress({
    duration = 6000,
    label = 'Glowing progress',
    animation = 'glow',
    type = 'linear',
    color = '#9C27B0'
})

Cancellation Handling

Basic Cancellation

-- Progress with cancellation support
local progressId = B2Lib.UI.progress({
    duration = 10000,
    label = 'Long operation (Press X to cancel)',
    canCancel = true,
    cancelKey = 'X',
    type = 'linear'
})

-- Handle cancellation in your code
CreateThread(function()
    local startTime = GetGameTimer()
    
    while GetGameTimer() - startTime < 10000 do
        local state = B2Lib.UI.getProgressState()
        
        if not state.active then
            print("Progress was cancelled")
            break
        end
        
        Wait(100)
    end
end)

Advanced Cancellation with Callback

-- Progress with custom cancellation handling
local function startCancellableOperation()
    local progressId = B2Lib.UI.progress({
        duration = 15000,
        label = 'Downloading large file... (ESC to cancel)',
        canCancel = true,
        cancelKey = 'ESC',
        type = 'linear',
        position = 'bottom-center'
    })
    
    -- Monitor for cancellation
    CreateThread(function()
        local cancelled = false
        
        while not cancelled do
            local state = B2Lib.UI.getProgressState()
            
            if not state.active then
                cancelled = true
                print("Download cancelled by user")
                
                -- Cleanup operations
                TriggerEvent('download:cancelled')
                
                -- Show cancellation notification
                B2Lib.UI.notify({
                    type = 'warning',
                    title = 'Download Cancelled',
                    message = 'File download was cancelled',
                    duration = 3000
                })
                break
            end
            
            Wait(100)
        end
    end)
end

Server-Side Usage

Progress for Specific Player

-- Progress for the player who triggered an event
RegisterNetEvent('server:longOperation')
AddEventHandler('server:longOperation', function()
    local source = source
    
    B2Lib.UI.progress(source, {
        duration = 5000,
        label = 'Processing your request...',
        type = 'circular',
        showPercentage = true,
        color = '#4CAF50'
    })
    
    -- Simulate server work
    SetTimeout(5000, function()
        B2Lib.UI.notify(source, {
            type = 'success',
            title = 'Complete',
            message = 'Your request has been processed!'
        })
    end)
end)

Progress for All Players

-- Send progress to all online players
local function progressAllPlayers(data)
    B2Lib.UI.progressAll(data)
end

-- Server maintenance example
progressAllPlayers({
    duration = 30000,
    label = 'Server maintenance in progress...',
    type = 'linear',
    position = 'top-center',
    canCancel = false,
    color = '#FF9800',
    size = 'large'
})

Sequential Server Operations

-- Chain multiple server-side progress operations
local function performServerTasks(playerId)
    -- Task 1: Initialization
    B2Lib.UI.progress(playerId, {
        duration = 3000,
        label = 'Initializing system...',
        type = 'circular',
        color = '#2196F3'
    })
    
    SetTimeout(3000, function()
        -- Task 2: Data processing
        B2Lib.UI.progress(playerId, {
            duration = 5000,
            label = 'Processing player data...',
            type = 'linear',
            showPercentage = true,
            color = '#FF9800',
            position = 'bottom-center'
        })
        
        SetTimeout(5000, function()
            -- Task 3: Finalization
            B2Lib.UI.progress(playerId, {
                duration = 2000,
                label = 'Finalizing...',
                type = 'circular',
                color = '#4CAF50',
                size = 'small'
            })
            
            SetTimeout(2000, function()
                B2Lib.UI.notify(playerId, {
                    type = 'success',
                    title = 'Complete',
                    message = 'All server tasks completed successfully!'
                })
            end)
        end)
    end)
end

-- Usage
RegisterNetEvent('server:performTasks')
AddEventHandler('server:performTasks', function()
    performServerTasks(source)
end)

Conditional Progress Operations

-- Progress based on player permissions or conditions
local function conditionalProgress(playerId, operationType)
    local duration = 5000
    local label = 'Processing...'
    local color = '#2196F3'
    
    if operationType == 'admin' then
        if IsPlayerAceAllowed(playerId, 'admin') then
            duration = 2000  -- Faster for admins
            label = 'Admin operation in progress...'
            color = '#9C27B0'
        else
            B2Lib.UI.notify(playerId, {
                type = 'error',
                title = 'Access Denied',
                message = 'Insufficient permissions'
            })
            return
        end
    elseif operationType == 'vip' then
        duration = 3000  -- Faster for VIP
        label = 'VIP operation in progress...'
        color = '#FFD700'
    end
    
    B2Lib.UI.progress(playerId, {
        duration = duration,
        label = label,
        type = 'circular',
        color = color,
        showPercentage = true
    })
end

Configuration

Configure progress bar defaults in config.lua:

Config.Progress = {
    position = 'center',              -- Default position
    showPercentage = true,            -- Show percentage by default
    defaultColor = 'primary',         -- Default color theme
    defaultType = 'circular',         -- Default progress type
    defaultSize = 'medium',           -- Default size
    enableGradient = true,            -- Enable gradient effects
    defaultAnimation = 'smooth',      -- Default animation style
    cancelKey = 'X',                  -- Default cancel key
    fadeTime = 300,                   -- Fade in/out duration
    updateInterval = 16               -- Update interval for smooth animation (60fps)
}

Config.ProgressStyles = {
    circular = {
        small = { size: 60, thickness: 6 },
        medium = { size: 80, thickness: 8 },
        large = { size: 120, thickness: 12 }
    },
    linear = {
        small = { width: 200, height: 4 },
        medium = { width: 300, height: 6 },
        large = { width: 400, height: 8 }
    },
    colors = {
        primary = '#3B82F6',
        success = '#10B981',
        warning = '#F59E0B',
        error = '#EF4444',
        info = '#06B6D4'
    }
}

Advanced Examples

Multi-Step Progress with Updates

-- Progress bar that updates its label and color during execution
local function multiStepProgress()
    local steps = {
        { duration: 2000, label: 'Connecting to server...', color: '#2196F3' },
        { duration: 3000, label: 'Authenticating user...', color: '#FF9800' },
        { duration: 2000, label: 'Loading user data...', color: '#9C27B0' },
        { duration: 1000, label: 'Finalizing...', color: '#4CAF50' }
    }
    
    local function executeStep(stepIndex)
        if stepIndex > #steps then
            B2Lib.UI.notify({
                type = 'success',
                title = 'Complete',
                message = 'All steps completed successfully!'
            })
            return
        end
        
        local step = steps[stepIndex]
        
        B2Lib.UI.progress({
            duration = step.duration,
            label = step.label,
            color = step.color,
            type = 'linear',
            showPercentage = true,
            position = 'bottom-center'
        })
        
        SetTimeout(step.duration, function()
            executeStep(stepIndex + 1)
        end)
    end
    
    executeStep(1)
end

Progress with Real-time Updates

-- Progress bar that shows real-time file download progress
local function downloadWithProgress(fileSize)
    local downloaded = 0
    local startTime = GetGameTimer()
    
    local progressId = B2Lib.UI.progress({
        duration = 10000,  -- Estimated duration
        label = 'Downloading file... 0%',
        type = 'linear',
        showPercentage = false,  -- We'll show custom percentage
        canCancel = true,
        position = 'bottom-center'
    })
    
    -- Simulate download progress
    CreateThread(function()
        while downloaded < fileSize do
            local progress = (downloaded / fileSize) * 100
            local speed = downloaded / ((GetGameTimer() - startTime) / 1000)  -- bytes per second
            
            -- Update progress label with custom information
            local label = string.format('Downloading... %.1f%% (%.1f KB/s)', 
                progress, speed / 1024)
            
            -- Note: This would require a custom update function
            -- For now, we simulate with periodic progress bars
            
            downloaded = downloaded + math.random(100, 500)  -- Simulate download chunks
            Wait(100)
        end
        
        B2Lib.UI.hideProgress()
        B2Lib.UI.notify({
            type = 'success',
            title = 'Download Complete',
            message = 'File downloaded successfully!'
        })
    end)
end

Progress with State Persistence

-- Progress system that remembers state across resource restarts
local progressState = {}

local function saveProgressState(id, state)
    progressState[id] = {
        startTime = GetGameTimer(),
        duration = state.duration,
        label = state.label,
        progress = state.progress
    }
end

local function restoreProgressState(id)
    local saved = progressState[id]
    if not saved then return false end
    
    local elapsed = GetGameTimer() - saved.startTime
    local remaining = saved.duration - elapsed
    
    if remaining > 0 then
        B2Lib.UI.progress({
            duration = remaining,
            label = saved.label,
            type = 'circular',
            showPercentage = true
        })
        return true
    end
    
    return false
end

-- Usage
local function startPersistentProgress(id, options)
    saveProgressState(id, options)
    return B2Lib.UI.progress(options)
end

Server-Side Batch Operations

-- Server-side batch processing with progress updates
local function processBatchOperation(playerId, items)
    local totalItems = #items
    local processedItems = 0
    
    local function processNextItem()
        if processedItems >= totalItems then
            B2Lib.UI.notify(playerId, {
                type = 'success',
                title = 'Batch Complete',
                message = string.format('Processed %d items successfully', totalItems)
            })
            return
        end
        
        processedItems = processedItems + 1
        local progress = (processedItems / totalItems) * 100
        
        B2Lib.UI.progress(playerId, {
            duration = 1000,  -- Time per item
            label = string.format('Processing item %d of %d (%.1f%%)', 
                processedItems, totalItems, progress),
            type = 'linear',
            showPercentage = false,  -- Using custom percentage in label
            color = '#4CAF50'
        })
        
        -- Simulate processing time
        SetTimeout(1000, function()
            processNextItem()
        end)
    end
    
    processNextItem()
end

-- Usage
RegisterNetEvent('server:batchProcess')
AddEventHandler('server:batchProcess', function(items)
    processBatchOperation(source, items)
end)

Events

The progress system triggers the following events:

Client-Side Events

  • b2lib:progress:started - Triggered when a progress bar starts

  • b2lib:progress:updated - Triggered during progress updates

  • b2lib:progress:completed - Triggered when progress completes

  • b2lib:progress:cancelled - Triggered when progress is cancelled

Server-Side Events

  • b2lib:server:progress - Internal event for server-to-client progress

  • b2lib:server:progressAll - Internal event for broadcasting progress

Best Practices

  1. Choose Appropriate Types - Use circular for indeterminate operations, linear for measurable progress

  2. Provide Clear Labels - Use descriptive labels that inform users what's happening

  3. Consider Duration - Match progress duration to actual operation time when possible

  4. Use Cancellation Wisely - Allow cancellation for long operations that users might want to abort

  5. Position Strategically - Place progress bars where they won't obstruct important UI elements

  6. Customize for Context - Use appropriate colors and sizes for different operation types

  7. Handle Edge Cases - Always validate parameters and handle failures gracefully

  8. Test Performance - Ensure progress animations don't impact game performance

  9. Provide Feedback - Show completion notifications after progress finishes

  10. Use Server-Side for Critical Operations - Important progress should be managed server-side

Troubleshooting

Progress Not Showing

  1. Check Duration Parameter: Ensure duration is provided and is a positive number

  2. Verify B2Lib Initialization: Confirm B2Lib is properly initialized

  3. Validate Position: Ensure position value is valid

  4. Check Console Errors: Look for error messages in the console

  5. Test with Simple Example: Try a basic progress bar without optional parameters

-- Simple test progress
B2Lib.UI.progress({
    duration = 3000,
    label = "Test progress"
})

Progress Animation Issues

  1. Check Update Interval: Verify updateInterval in config is appropriate (16ms for 60fps)

  2. Monitor Performance: Ensure other scripts aren't causing frame drops

  3. Test Different Types: Try both circular and linear types

  4. Disable Effects: Temporarily disable gradient and animation effects

Cancellation Not Working

  1. Verify canCancel Setting: Ensure canCancel is set to true

  2. Check Cancel Key: Verify the cancel key is properly configured

  3. Test Key Binding: Ensure the cancel key isn't bound to other functions

  4. Monitor State: Use getProgressState() to check cancellation status

Server-Side Issues

  1. Check Player Validity: Ensure player ID is valid before sending progress

  2. Handle Disconnections: Account for players disconnecting during progress

  3. Validate Permissions: Check player permissions before showing progress

  4. Test Event Triggering: Verify server events are properly registered

Performance Issues

  1. Limit Concurrent Progress: Avoid multiple progress bars simultaneously

  2. Optimize Update Frequency: Adjust update interval based on needs

  3. Use Appropriate Sizes: Smaller progress bars have better performance

  4. Monitor Memory Usage: Check for memory leaks with long-running progress


Last updated