Common ImGui Widgets and Their Usage: A Complete Guide to Dear ImGui UI Elements

Dear ImGui provides a comprehensive set of immediate-mode widgets—including buttons, checkboxes, radio buttons, sliders, text inputs, and color editors—implemented in imgui_widgets.cpp using a standard four-stage pipeline of ID generation, layout calculation, interaction handling via ButtonBehavior, and rendering.

The open-source library Dear ImGui (ocornut/imgui) offers a robust collection of immediate-mode graphical user interface elements designed for debugging tools and internal development panels. Understanding the common ImGui widgets and their usage patterns is essential for building efficient tool UIs that integrate seamlessly with your application. These widgets share a unified architecture in imgui_widgets.cpp that handles input, state management, and rendering through a consistent API surface.

Core Widget Architecture in Dear ImGui

Every widget in the ImGui library follows a standardized execution flow that ensures consistent behavior and interaction handling. This architecture is implemented in imgui_widgets.cpp and consists of four critical stages:

  1. ID Generation – Each widget calls window->GetID(label) (or uses a supplied string) to obtain a unique ImGuiID used for tracking interaction state across frames. This occurs at lines 94-97 in imgui_widgets.cpp.
  2. Item Layout – The widget calculates its size using CalcItemSize and reserves space via ItemSize. It then creates an ImRect (bb) representing the clickable region (lines 98-105).
  3. Interaction Handling – The core function ButtonBehavior determines whether the item is hovered, held, or pressed, using the generated ID and the bounding rectangle (lines 84-86).
  4. Rendering – After determining interaction results, each widget renders its visual representation using the current style and color settings (lines 112-118).

This pipeline ensures that all common ImGui widgets behave predictably while maintaining the library's immediate-mode philosophy.

Essential ImGui Widgets and Code Examples

The following sections cover the most frequently used widgets in the Dear ImGui library, including their typical API signatures and minimal implementation examples. All examples assume an active ImGui frame initiated with ImGui::Begin.

Button Widgets and Interactive Elements

Button is the fundamental clickable widget used to trigger actions. It returns true when clicked during the current frame.

if (ImGui::Button("Save")) {
    // Trigger save action
}

SmallButton provides a compact alternative that fits inline with text, implemented in imgui_widgets.cpp (lines 334-342).

ImGui::Text("Options:"); ImGui::SameLine();
if (ImGui::SmallButton("Reset")) Reset();

InvisibleButton creates a clickable area without visual appearance, useful for custom drawing or drag handles (lines 444-464).

ImGui::InvisibleButton("##drag", ImVec2(200,20));
if (ImGui::IsItemActive()) {
    // Handle drag logic
}

Boolean and Selection Inputs

Checkbox toggles a boolean value and is implemented in imgui_widgets.cpp (lines 1242-1249).

static bool show_grid = true;
ImGui::Checkbox("Show grid", &show_grid);

CheckboxFlags manipulates bit-flags using checkbox interactions, supporting int, unsigned, ImS64, and ImU64 types (lines 1346-1363).

int flags = 0;
ImGui::CheckboxFlags("Enable Debug", &flags, ImGuiConfigFlags_DebugLog);

RadioButton selects one item among many options, returning true when the button becomes active (lines 1366-1375).

static int mode = 0;
ImGui::RadioButton("Copy", &mode, 0);
ImGui::SameLine(); ImGui::RadioButton("Move", &mode, 1);

Numeric Input Widgets

SliderFloat and SliderInt allow drag-to-adjust scalar values within a defined range using a visible track (lines 1439-1452).

static float speed = 1.0f;
ImGui::SliderFloat("Speed", &speed, 0.0f, 10.0f);

DragFloat and DragInt provide similar functionality without the visible track, offering precise numeric entry suitable for values requiring fine adjustment (lines 1459-1472).

static float angle = 0.0f;
ImGui::DragFloat("Angle", &angle, 0.1f);

Text Input Fields

InputText creates an editable single-line text field (lines 1669-1680).

static char name[64] = "";
ImGui::InputText("Name", name, IM_ARRAYSIZE(name));

InputTextMultiline provides a multi-line text editor with configurable size (lines 1700-1712).

static char notes[256] = "";
ImGui::InputTextMultiline("Notes", notes, IM_ARRAYSIZE(notes), ImVec2(0,100));

Selection and List Widgets

Combo creates a drop-down selection list using the BeginCombo/EndCombo pattern (lines 1786-1804).

static int current = 0;
const char* items[] = {"One","Two","Three"};
if (ImGui::BeginCombo("##combo", items[current])) {
    for (int i=0; i<3; i++)
        if (ImGui::Selectable(items[i], i==current))
            current=i;
    ImGui::EndCombo();
}

Selectable represents individual selectable rows, often used within tables or lists (lines 2035-2048).

static int selected = -1;
for (int i=0; i<5; i++)
    if (ImGui::Selectable(name[i], selected==i))
        selected = i;

ListBox provides a scrollable list with optional selection handling (lines 2080-2094).

static int cur = 0;
const char* fruits[] = {"Apple","Banana","Cherry"};
ImGui::ListBox("Fruits", &cur, fruits, IM_ARRAYSIZE(fruits));

Visual and Data Display Widgets

ColorEdit3 and ColorEdit4 provide inline color pickers for RGB and RGBA values respectively (lines 1840-1855).

static float col[3] = {1.0f, 0.0f, 0.0f};
ImGui::ColorEdit3("Tint", col);

Image and ImageButton display textures with optional interaction (lines 1900-1911).

ImGui::Image(my_texture, ImVec2(64,64));
if (ImGui::ImageButton(my_texture, ImVec2(32,32)))
    OpenSettings();

ProgressBar displays scalar progress between 0 and 1 (lines 1955-1967).

ImGui::ProgressBar(downloaded/total_size, ImVec2(0,0), "Downloading…");

PlotLines and PlotHistogram render quick inline visualizations of data series (lines 2120-2135).

float data[100];
// Fill data array...
ImGui::PlotLines("Signal", data, 100);

Container and Layout Widgets

TreeNode and CollapsingHeader create hierarchical containers that expand and collapse (lines 2000-2009).

if (ImGui::TreeNode("Settings")) {
    ImGui::Checkbox("VSync", &vsync);
    ImGui::TreePop();
}

Bullet renders a small dot used for list items (lines 1975-1982).

ImGui::Bullet(); ImGui::SameLine(); ImGui::Text("First item");

Key Implementation Files

Understanding the source structure of Dear ImGui helps when debugging or extending widget functionality:

  • imgui.h – Contains public API declarations and widget function signatures.
  • imgui_internal.h – Provides internal helpers including ButtonBehavior, CalcItemSize, and ItemAdd used by all widgets.
  • imgui_widgets.cpp – Houses the core widget implementations including Button, Checkbox, Slider, InputText, and Combo.
  • imgui_draw.cpp – Contains low-level rendering primitives for frames, arrows, and bullets.
  • imgui_demo.cpp – Offers comprehensive live demonstrations showing usage patterns for every common widget.

Summary

  • Common ImGui widgets follow a standardized four-stage architecture: ID generation via GetID, layout calculation using CalcItemSize, interaction detection through ButtonBehavior, and final rendering.
  • Button variants include standard Button, compact SmallButton, and invisible InvisibleButton for custom interactions.
  • Input widgets range from boolean checkboxes and radio buttons to numeric sliders, drag controls, and text input fields.
  • Selection widgets like Combo, Selectable, and ListBox manage choice states with immediate-mode patterns.
  • Specialized widgets such as ColorEdit, Image, ProgressBar, and PlotLines handle data visualization and media display.
  • All widgets are implemented in imgui_widgets.cpp and integrate with the internal state management system through unique IDs and bounding rectangles.

Frequently Asked Questions

What is the difference between SliderFloat and DragFloat in ImGui?

SliderFloat renders a visible track that users can click and drag to set values within a range, while DragFloat provides a drag-anywhere interaction without the visual track, making it better suited for precise numeric entry or values without strict bounds. Both are implemented in imgui_widgets.cpp and follow the same underlying architecture but differ in their visual presentation and default interaction sensitivity.

How does ImGui track widget state across frames?

Dear ImGui uses a hash-based ID system where each widget generates a unique ImGuiID by calling window->GetID(label) with its label or an explicit ID string. This ID is used by ButtonBehavior and other internal functions to track hover states, active states, and keyboard focus persistently across frames. The ID is computed from the current window ID stack combined with the widget's label as implemented in imgui_widgets.cpp (lines 94-97).

Can I create custom widgets using Dear ImGui's internal functions?

Yes, you can build custom widgets by following the standard widget flow: generate an ID using GetID, create a bounding ImRect, call ButtonBehavior to handle interactions, and then render using the ImDrawList API. This approach ensures your custom widgets integrate seamlessly with ImGui's state handling, styling system, and input processing, as demonstrated by the native implementations in imgui_widgets.cpp.

What is the purpose of the invisible button widget?

InvisibleButton creates a clickable hit-testing area without rendering any visual elements, making it ideal for implementing custom-drawn elements, drag handles, or interactive overlays where you want to handle input through ImGui's standard interaction system while providing your own visual representation. It uses the same ButtonBehavior function as visible buttons but skips the rendering phase.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →