Skip to content

Add a "HyperLink" control (clickable text with link-like styling) #7660

@seanmiddleditch

Description

@seanmiddleditch

Version/Branch of Dear ImGui:

Version 1.90.7, Branch: master

Back-ends:

Any (Unity/C# integration most recent case)

Compiler, OS:

Any (Windows, Unity C# 2022.x in most recent case)

Full config/build information:

No response

Details:

Feature Request

A small control that I've written for past projects and which we implemented at Wargaming, Blizzard (SGE), and at my current employer is a "HyperLink" widget, so it seems to me to be a frequently recurring pattern.

A hyperlink is some Text but which is rendered in a different color (e.g. blue) and has an underline, changes color slightly when hovered, and responds to clicks like a button, etc.

For users, this would be something like:

if (ImGui::HyperLink("Some label##id"))
  DoThing();

Writing the most basic version of this is almost trivial, of course, but it gets a bit trickier once things like keyboard focus and activation are considered, and really tricky to handle keyboard focus styling well. Every single implementation of such a control that I've seen (including mine!) got some or all of those wrong initially. I'm still not sure that I've seen one that handles word-wrap and focus highlight correctly, now that I think about it.

Having something like this in dear imgui itself instead of being reimplemented (often poorly) would be a small win.

Screenshots/Video:

Example of what a HyperLink control might look like:

image

And focused (styling could be better, just a quick demo here):
image

Minimal, Complete and Verifiable Example code:

// Crappy HyperLink implemented in a few minutes
//
// Does not handle: wordwrap
// Focus handling is not quite right (focus item stays after clicking with the mouse; ideally would be only outlined if keyboard was used to select/activate most recently)
// More input options for buttons, etc.
// Lacks custom style options. uses hard-coded colors
// Lacks a flag or style/color for "visited" links
// Lacks disabled link style/color
// Option to only show underline on hover could be a style? Or part of flags
bool ImGui::HyperLink(const char* label, bool underlineWhenHoveredOnly = false)
{
    const ImU32 linkColor = ImGui::ColorConvertFloat4ToU32({0.2, 0.3, 0.8, 1});
    const ImU32 linkHoverColor = ImGui::ColorConvertFloat4ToU32({0.4, 0.6, 0.8, 1});
    const ImU32 linkFocusColor = ImGui::ColorConvertFloat4ToU32({0.6, 0.4, 0.8, 1});

    const ImGuiID id = ImGui::GetID(label);

    ImGuiWindow* const window = ImGui::GetCurrentWindow();
    ImDrawList* const draw = ImGui::GetWindowDrawList();

    const ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
    const ImVec2 size = ImGui::CalcTextSize(label);
    ImRect bb(pos, {pos.x + size.x, pos.y + size.y});

    ImGui::ItemSize(bb, 0.0f);
    if (!ImGui::ItemAdd(bb, id))
        return false;

    bool isHovered = false;
    const bool isClicked = ImGui::ButtonBehavior(bb, id, &isHovered, nullptr);
    const bool isFocused = ImGui::IsItemFocused();

    const ImU32 color = isHovered ? linkHoverColor : isFocused ? linkFocusColor : linkColor;

    draw->AddText(bb.Min, color, label);

    if (isFocused)
        draw->AddRect(bb.Min, bb.Max, color);
    else if (!underlineWhenHoveredOnly || isHovered)
        draw->AddLine({ bb.Min.x, bb.Max.y }, bb.Max, color);

    return isClicked;
}
// Test code that generated the screenshot
if (ImGui::Begin("Test Hyperlink"))
{
    static bool clicked = false;
    ImGui::Text("%s", clicked ? "YES" : "NO");

    ImGui::Text("This is a link."); ImGui::SameLine();
    if (ImGuiHyperLink("Click me!"))
        clicked = !clicked;
    if (ImGui::BeginItemTooltip())
    {
        ImGui::Text("Click to toggle");
        ImGui::EndTooltip();
    }

    ImGui::SameLine(); ImGui::Text("That was a link.");
}
ImGui::End();

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions