> ## Documentation Index
> Fetch the complete documentation index at: https://lationscripts.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Modern UI - List Menu

> Keyboard-driven list menus with scrollable values, checkboxes, and progress bars

List menus are compact, keyboard-only menus navigated with the arrow keys - a modern drop-in replacement for ox\_lib's `lib.registerMenu`/`lib.showMenu` with the same callbacks, indices, and keybinds. Rows can side-scroll through values, toggle checkboxes, and display progress bars, with a built-in description panel and contextual key hints.

<Note>
  Looking for the mouse-driven menu with submenus and hover metadata? That's the [Menu](/docs/modern-ui/components/menu) component. The list menu is its keyboard-only sibling: flat, single-level, and driven entirely by arrow keys.
</Note>

## Quick Start

```lua theme={null}
exports.lation_ui:registerListMenu({
    id = 'vehicle_settings',
    title = 'Vehicle Settings',
    subtitle = 'Sultan RS',
    icon = 'fas fa-sliders',
    options = {
        {
            label = 'Radio Station',
            icon = 'fas fa-radio',
            description = 'Scroll through available stations',
            values = { 'Non-Stop-Pop', 'Los Santos Rock', 'WCTR' },
            defaultIndex = 2
        },
        {
            label = 'Lock Doors',
            icon = 'fas fa-lock',
            description = 'Toggle the vehicle door locks',
            checked = true
        },
        {
            label = 'Start Driving',
            icon = 'fas fa-gauge-high',
            description = 'Head to the first waypoint',
            args = { waypoint = 1 }
        }
    }
}, function(selected, scrollIndex, args, checked)
    print('Confirmed option', selected, scrollIndex, checked)
end)

exports.lation_ui:showListMenu('vehicle_settings')
```

## Functions

<AccordionGroup>
  <Accordion title="registerListMenu" icon="plus">
    Register a new list menu with the specified configuration.

    ```lua theme={null}
    exports.lation_ui:registerListMenu(menuData, cb)
    ```

    **Parameters:**

    * `menuData` (table) - Menu configuration object (see [Registration Options](#registration-options))
    * `cb` (function, optional) - Called when an option is confirmed with Enter: `cb(selected, scrollIndex, args, checked)`
  </Accordion>

  <Accordion title="showListMenu" icon="eye">
    Display a previously registered list menu.

    ```lua theme={null}
    exports.lation_ui:showListMenu(menuId, startIndex)
    ```

    **Parameters:**

    * `menuId` (string) - Unique identifier of the menu to display
    * `startIndex` (number, optional) - 1-based option to highlight on open
  </Accordion>

  <Accordion title="hideListMenu" icon="eye-slash">
    Hide the currently displayed list menu.

    ```lua theme={null}
    exports.lation_ui:hideListMenu(onExit)
    ```

    **Parameters:**

    * `onExit` (boolean, optional) - `true` also fires the menu's `onClose` callback
  </Accordion>

  <Accordion title="setListMenuOptions" icon="rotate">
    Replace a registered menu's options - a single option (with `index`) or all of them.

    ```lua theme={null}
    exports.lation_ui:setListMenuOptions(menuId, options, index)
    ```

    **Parameters:**

    * `menuId` (string) - Unique identifier of the menu to update
    * `options` (table) - A single option (when `index` is given) or an array of options
    * `index` (number, optional) - 1-based option index to replace

    <Note>
      If the menu is currently open, the change applies **live** - no re-register or re-open needed. The player's selection is kept.
    </Note>
  </Accordion>

  <Accordion title="getOpenListMenu" icon="question">
    Get the ID of the currently open list menu.

    ```lua theme={null}
    local menuId = exports.lation_ui:getOpenListMenu()
    ```

    **Returns:**

    * `menuId` (string | nil) - The ID of the currently open list menu, or nil if none is open
  </Accordion>
</AccordionGroup>

## Keyboard Controls

| Key                 | Action                                                            |
| ------------------- | ----------------------------------------------------------------- |
| `↑` / `↓`           | Move the selection (wraps around, skips disabled options)         |
| `←` / `→`           | Scroll through an option's `values` (wraps around)                |
| `Enter`             | Confirm the selected option, or toggle a checkbox option in place |
| `Home` / `End`      | Jump to the first / last option                                   |
| `ESC` / `Backspace` | Close the menu (blocked when `canClose = false`)                  |

While a list menu is open the cursor stays hidden and the player keeps game input (walking, driving) unless `disableInput = true`. Firing, the weapon wheel, and melee are always disabled.

## Configuration

### Registration Options

<ParamField path="id" type="string" required>
  Unique menu identifier
</ParamField>

<ParamField path="title" type="string" required>
  Menu title (supports markdown)
</ParamField>

<ParamField path="subtitle" type="string">
  Menu subtitle (supports markdown)
</ParamField>

<ParamField path="icon" type="string">
  FontAwesome icon class or image URL

  Supported image formats: `.png`, `.webp`, `.jpg`, `.jpeg`, `.gif`, `.svg`
</ParamField>

<ParamField path="iconColor" default="#9CA3AF" type="string">
  Icon color (hex or [CSS color name](https://htmlcolorcodes.com/color-names/))
</ParamField>

<ParamField path="iconAnimation" type="string">
  Icon animation: `'spin'`, `'spinPulse'`, `'spinReverse'`, `'pulse'`, `'beat'`, `'fade'`, `'beatFade'`, `'bounce'`, `'shake'`
</ParamField>

<ParamField path="position" default="top-left" type="string">
  Menu position. Available options: `'top-left'`, `'top-right'`, `'bottom-left'`, `'bottom-right'`
</ParamField>

<ParamField path="canClose" default="true" type="boolean">
  Whether the menu can be closed with ESC/Backspace
</ParamField>

<ParamField path="disableInput" default="false" type="boolean">
  `true` freezes game input while the menu is open (by default the player keeps moving control)
</ParamField>

<ParamField path="onClose" type="function">
  Called when the menu is closed by the player: `onClose(keyPressed)` where `keyPressed` is `'Escape'`, `'Backspace'`, or nil when closed via `hideListMenu(true)`
</ParamField>

<ParamField path="onSelected" type="function">
  Called when the highlighted option changes: `onSelected(selected, secondary, args)`

  `secondary` is the 1-based scroll index on a `values` option, or the checked state on a checkbox option
</ParamField>

<ParamField path="onSideScroll" type="function">
  Called when a `values` option is scrolled: `onSideScroll(selected, scrollIndex, args)`
</ParamField>

<ParamField path="onCheck" type="function">
  Called when a checkbox option is toggled: `onCheck(selected, checked, args)`
</ParamField>

<ParamField path="options" type="table" required>
  Array of menu options (see [Option Properties](#option-properties))
</ParamField>

### Option Properties

<ParamField path="label" type="string" required>
  Option display text (supports markdown)
</ParamField>

<ParamField path="icon" type="string">
  FontAwesome icon class or image URL

  Supported image formats: `.png`, `.webp`, `.jpg`, `.jpeg`, `.gif`, `.svg`
</ParamField>

<ParamField path="iconColor" default="#9CA3AF" type="string">
  Icon color (hex or [CSS color name](https://htmlcolorcodes.com/color-names/))
</ParamField>

<ParamField path="iconAnimation" type="string">
  Icon animation type

  Available options: `'spin'`, `'spinPulse'`, `'spinReverse'`, `'pulse'`, `'beat'`, `'fade'`, `'beatFade'`, `'bounce'`, `'shake'`
</ParamField>

<ParamField path="description" type="string">
  Shown in the description panel below the list while this option is selected (supports markdown)
</ParamField>

<ParamField path="values" type="table">
  Makes the option side-scrollable with `←`/`→` (see [Values](#values))
</ParamField>

<ParamField path="defaultIndex" default="1" type="number">
  1-based initial scroll index for a `values` option
</ParamField>

<ParamField path="checked" type="boolean">
  Makes the option a checkbox toggled in place with Enter. Set `true` or `false` for the initial state - the presence of the field is what creates the checkbox
</ParamField>

<ParamField path="progress" type="number">
  Progress bar value (0-100) rendered under the label
</ParamField>

<ParamField path="progressColor" default="#3B82F6" type="string">
  Progress bar color (hex or [CSS color name](https://htmlcolorcodes.com/color-names/))

  <Note>
    Can also use `colorScheme` as an alias
  </Note>
</ParamField>

<ParamField path="disabled" default="false" type="boolean">
  Rendered dimmed and skipped by keyboard navigation
</ParamField>

<ParamField path="close" default="true" type="boolean">
  Whether confirming this option closes the menu (`false` keeps it open)
</ParamField>

<ParamField path="args" type="table">
  Arguments passed to the confirm callback and events
</ParamField>

<ParamField path="onSelect" type="function">
  Callback executed when the option is confirmed: `onSelect(selected, scrollIndex, args)`
</ParamField>

<ParamField path="event" type="string">
  Client event to trigger when the option is confirmed
</ParamField>

<ParamField path="serverEvent" type="string">
  Server event to trigger when the option is confirmed
</ParamField>

### Values

Each entry in `values` is either a plain string or an object with its own description, which replaces the option's `description` while that value is selected:

```lua theme={null}
values = {
    'Non-Stop-Pop',
    'Los Santos Rock',
    { label = 'WCTR', description = 'Talk radio - West Coast Talk Radio' }
}
```

## Behavior Notes

* **Live updates** - `setListMenuOptions` applies to an open menu immediately, keeping the player's selection.
* **State persistence** - scroll positions and checkbox states are remembered when a menu is closed and re-shown. Re-register the menu to reset them.
* **Switching menus** - calling `showListMenu` while another list menu is open switches directly without firing the first menu's `onClose`.

## Migrating from ox\_lib

The API is deliberately signature-compatible with ox\_lib's list menu - same 1-based indices, same callbacks, same keybinds:

| ox\_lib                                  | lation\_ui                                                 |
| ---------------------------------------- | ---------------------------------------------------------- |
| `lib.registerMenu(data, cb)`             | `exports.lation_ui:registerListMenu(data, cb)`             |
| `lib.showMenu(id, startIndex)`           | `exports.lation_ui:showListMenu(id, startIndex)`           |
| `lib.hideMenu(onExit)`                   | `exports.lation_ui:hideListMenu(onExit)`                   |
| `lib.setMenuOptions(id, options, index)` | `exports.lation_ui:setListMenuOptions(id, options, index)` |
| `lib.getOpenMenu()`                      | `exports.lation_ui:getOpenListMenu()`                      |

<Note>
  Using our [ox\_lib fork](https://github.com/IamLation/ox_lib/releases/latest)? `lib.registerMenu` and friends forward to the list menu automatically while lation\_ui is running - existing scripts need **no changes at all**.
</Note>

## Preview

<Frame>
  <img src="https://mintcdn.com/lationscripts/Eaqs74Ga_7blVGdw/resources/modern-ui/components/list-menu/list-menu-example-1.webp?fit=max&auto=format&n=Eaqs74Ga_7blVGdw&q=85&s=7d16c86a961d0b90309884ab4cc777fc" alt="List Menu Preview" width="872" height="854" data-path="resources/modern-ui/components/list-menu/list-menu-example-1.webp" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/lationscripts/Eaqs74Ga_7blVGdw/resources/modern-ui/components/list-menu/list-menu-example-2.webp?fit=max&auto=format&n=Eaqs74Ga_7blVGdw&q=85&s=b344b6a495386b333f6e259a7d687e46" alt="List Menu Preview" width="872" height="854" data-path="resources/modern-ui/components/list-menu/list-menu-example-2.webp" />
</Frame>
