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

# Combos and Lists

> Dropdown menus and list boxes in Dear ImGui

Combo boxes (dropdowns) and list boxes provide ways for users to select from a list of options. Dear ImGui offers both simple helper functions and flexible BeginCombo/EndCombo APIs.

## Combo Boxes

### BeginCombo() / EndCombo()

Manually control combo box contents:

```cpp theme={null}
IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
IMGUI_API void EndCombo();
```

<ParamField path="label" type="const char*" required>
  Widget label
</ParamField>

<ParamField path="preview_value" type="const char*" required>
  Text displayed in the combo box before opening
</ParamField>

<ParamField path="flags" type="ImGuiComboFlags">
  Optional combo flags (see below)
</ParamField>

```cpp theme={null}
const char* items[] = { "Apple", "Banana", "Cherry", "Dragon Fruit" };
static int item_current_idx = 0;
const char* combo_preview_value = items[item_current_idx];

if (ImGui::BeginCombo("Fruit", combo_preview_value)) {
    for (int n = 0; n < IM_COUNTOF(items); n++) {
        const bool is_selected = (item_current_idx == n);
        if (ImGui::Selectable(items[n], is_selected))
            item_current_idx = n;
        
        // Set initial focus when opening the combo
        if (is_selected)
            ImGui::SetItemDefaultFocus();
    }
    ImGui::EndCombo();
}
```

<Note>
  Only call `EndCombo()` if `BeginCombo()` returns true!
</Note>

### Simple Combo() Functions

Convenience wrappers for common use cases:

```cpp theme={null}
IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count,
                     int popup_max_height_in_items = -1);
IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros,
                     int popup_max_height_in_items = -1);
IMGUI_API bool Combo(const char* label, int* current_item,
                     const char* (*getter)(void* user_data, int idx), void* user_data,
                     int items_count, int popup_max_height_in_items = -1);
```

<Tabs>
  <Tab title="Array of Strings">
    ```cpp theme={null}
    const char* items[] = { "AAA", "BBB", "CCC", "DDD" };
    static int item_current = 0;
    ImGui::Combo("Combo", &item_current, items, IM_COUNTOF(items));
    ```
  </Tab>

  <Tab title="Null-Separated String">
    ```cpp theme={null}
    static int item_current = 0;
    ImGui::Combo("Combo", &item_current, "One\0Two\0Three\0Four\0\0");
    ```
  </Tab>

  <Tab title="Getter Function">
    ```cpp theme={null}
    const char* items[] = { "AAA", "BBB", "CCC" };
    static int item_current = 0;

    auto getter = [](void* data, int n) -> const char* {
        return ((const char**)data)[n];
    };

    ImGui::Combo("Combo", &item_current, getter, items, IM_COUNTOF(items));
    ```
  </Tab>
</Tabs>

## Combo Flags

### Popup Alignment

```cpp theme={null}
// Align popup to left (useful if combo is wider than popup)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_PopupAlignLeft);
```

### Height

```cpp theme={null}
// Small popup (4 items visible)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightSmall);

// Regular popup (8 items visible, default)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightRegular);

// Large popup (20 items visible)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightLarge);

// Largest popup (as many fitting items as possible)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_HeightLargest);
```

### Button Style

```cpp theme={null}
// No arrow button
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_NoArrowButton);

// No preview text (button only)
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_NoPreview);

// Width matches preview text width
ImGui::BeginCombo("##combo", preview, ImGuiComboFlags_WidthFitPreview);
```

## Combo with Search Filter

Add filtering to combo box contents:

```cpp theme={null}
const char* items[] = { "Apple", "Apricot", "Banana", "Blueberry", "Cherry" };
static int item_current_idx = 0;
const char* combo_preview_value = items[item_current_idx];

if (ImGui::BeginCombo("Fruits", combo_preview_value)) {
    static ImGuiTextFilter filter;
    
    // Focus search box when opening
    if (ImGui::IsWindowAppearing()) {
        ImGui::SetKeyboardFocusHere();
        filter.Clear();
    }
    
    // Search box
    filter.Draw("##filter", -FLT_MIN);
    
    // Filtered items
    for (int n = 0; n < IM_COUNTOF(items); n++) {
        const bool is_selected = (item_current_idx == n);
        if (filter.PassFilter(items[n])) {
            if (ImGui::Selectable(items[n], is_selected))
                item_current_idx = n;
        }
    }
    
    ImGui::EndCombo();
}
```

## List Boxes

### BeginListBox() / EndListBox()

Create a scrollable list:

```cpp theme={null}
IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0));
IMGUI_API void EndListBox();
```

<ParamField path="size" type="ImVec2">
  * `size.x > 0.0f`: Custom width
  * `size.x < 0.0f or -FLT_MIN`: Right-align
  * `size.x = 0.0f`: Use current ItemWidth
  * `size.y > 0.0f`: Custom height
  * `size.y < 0.0f or -FLT_MIN`: Bottom-align
  * `size.y = 0.0f`: Default height (\~7 items)
</ParamField>

```cpp theme={null}
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE" };
static int item_selected_idx = 0;

if (ImGui::BeginListBox("##listbox")) {
    for (int n = 0; n < IM_COUNTOF(items); n++) {
        const bool is_selected = (item_selected_idx == n);
        if (ImGui::Selectable(items[n], is_selected))
            item_selected_idx = n;
        
        // Set initial focus when opening
        if (is_selected)
            ImGui::SetItemDefaultFocus();
    }
    ImGui::EndListBox();
}
```

### Custom Sized List Box

```cpp theme={null}
// Full width, 5 items tall
if (ImGui::BeginListBox("##listbox2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) {
    for (int n = 0; n < IM_COUNTOF(items); n++) {
        bool is_selected = (item_selected_idx == n);
        if (ImGui::Selectable(items[n], is_selected))
            item_selected_idx = n;
    }
    ImGui::EndListBox();
}
```

### Simple ListBox() Function

Convenience wrapper:

```cpp theme={null}
IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[],
                       int items_count, int height_in_items = -1);
IMGUI_API bool ListBox(const char* label, int* current_item,
                       const char* (*getter)(void* user_data, int idx), void* user_data,
                       int items_count, int height_in_items = -1);
```

```cpp theme={null}
const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange" };
static int item_current = 1;
ImGui::ListBox("Listbox", &item_current, items, IM_COUNTOF(items), 4);
```

## Highlighting Hovered Items

```cpp theme={null}
static int item_selected = 0;
static int item_highlighted = -1;

if (ImGui::BeginListBox("##listbox")) {
    for (int n = 0; n < IM_COUNTOF(items); n++) {
        const bool is_selected = (item_selected == n);
        ImGuiSelectableFlags flags = 0;
        
        if (item_highlighted == n)
            flags |= ImGuiSelectableFlags_Highlight;
        
        if (ImGui::Selectable(items[n], is_selected, flags))
            item_selected = n;
        
        if (ImGui::IsItemHovered())
            item_highlighted = n;
        
        if (is_selected)
            ImGui::SetItemDefaultFocus();
    }
    ImGui::EndListBox();
}
```

## Multi-Column Lists

Combine list boxes with tables:

```cpp theme={null}
if (ImGui::BeginListBox("##listbox3", ImVec2(-FLT_MIN, 0))) {
    if (ImGui::BeginTable("##table", 3)) {
        static int selected = -1;
        
        for (int i = 0; i < 10; i++) {
            ImGui::TableNextRow();
            ImGui::TableNextColumn();
            
            char label[32];
            sprintf(label, "Item %d", i);
            if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
                selected = i;
            
            ImGui::TableNextColumn();
            ImGui::Text("Column 2");
            
            ImGui::TableNextColumn();
            ImGui::Text("Data %d", i * 10);
        }
        ImGui::EndTable();
    }
    ImGui::EndListBox();
}
```

## Complete Example

```cpp theme={null}
void ShowComboListDemo() {
    ImGui::Begin("Combo & List Demo");
    
    // Simple combo
    ImGui::Text("Simple Combo:");
    const char* items[] = { "Apple", "Banana", "Cherry", "Dragon Fruit" };
    static int combo_current = 0;
    ImGui::Combo("Fruit", &combo_current, items, IM_COUNTOF(items));
    
    ImGui::Spacing();
    
    // Custom combo with BeginCombo/EndCombo
    ImGui::Text("Custom Combo:");
    static int item_current_idx = 0;
    const char* combo_preview = items[item_current_idx];
    
    if (ImGui::BeginCombo("Custom", combo_preview, ImGuiComboFlags_HeightLarge)) {
        for (int n = 0; n < IM_COUNTOF(items); n++) {
            const bool is_selected = (item_current_idx == n);
            if (ImGui::Selectable(items[n], is_selected))
                item_current_idx = n;
            if (is_selected)
                ImGui::SetItemDefaultFocus();
        }
        ImGui::EndCombo();
    }
    
    ImGui::Spacing();
    ImGui::Separator();
    ImGui::Spacing();
    
    // List box
    ImGui::Text("List Box:");
    static int list_current = 0;
    
    if (ImGui::BeginListBox("##listbox", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) {
        for (int n = 0; n < IM_COUNTOF(items); n++) {
            const bool is_selected = (list_current == n);
            if (ImGui::Selectable(items[n], is_selected))
                list_current = n;
            if (is_selected)
                ImGui::SetItemDefaultFocus();
        }
        ImGui::EndListBox();
    }
    
    ImGui::End();
}
```

## Performance Tips

For large lists, use `ImGuiListClipper` to only render visible items:

```cpp theme={null}
if (ImGui::BeginListBox("##large_list", ImVec2(-FLT_MIN, 0))) {
    ImGuiListClipper clipper;
    clipper.Begin(1000);  // 1000 items
    
    while (clipper.Step()) {
        for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
            char label[32];
            sprintf(label, "Item %d", i);
            if (ImGui::Selectable(label, selected == i))
                selected = i;
        }
    }
    
    ImGui::EndListBox();
}
```

## Best Practices

<Tip>
  Use `BeginCombo()` / `EndCombo()` for full control over combo contents, including filtering and custom rendering.
</Tip>

<Warning>
  Always call `EndCombo()` or `EndListBox()` only if the corresponding Begin function returned true.
</Warning>

<Note>
  Call `SetItemDefaultFocus()` on the selected item to ensure proper keyboard navigation when the popup opens.
</Note>
