Skip to content

InfoBar

Header: winui/ui/status/InfoBar.hpp. Spec: winui/ui/status/InfoBar.hpp.

An inline, closable banner that shows an app-wide status message with a severity color and icon.

A freshly built bar is closed: it takes no room and draws nothing until set_open(true). Title, message and the optional action button sit on one line when they fit and stack (wrapping at whole words) when they don't; the bar is at least 48 DIPs tall. Optional custom content (set_content()) gets a row of its own below them. The InfoBar itself is never a tab stop. Its action button, its content's controls and its close button are.

Closing runs in a fixed order: a close-button click first raises on_close_button_click(), then on_closing() (return ui::Cancel to keep it open, leaving is_open() true). Only a close that goes ahead flips is_open() to false and raises on_closed(). set_open(false) runs the same on_closing() and on_closed() sequence with reason Programmatic. Reopening raises nothing.

Example:

// Declarative, with the open state in a Property:
ui::Property<bool> open{true};
window.set_content(ui::InfoBar{
    .title     = "Update available",
    .message   = "Restart the app to apply the update.",
    .is_open   = open,
    .severity  = ui::InfoBarSeverity::Success,
    .on_closed = [&open](ui::PopupCloseReason) { open = false; },
    .action_button_content = ui::Button{.text = "Restart", .on_click = [] { restart_app(); }},
});

// Imperative:
auto  stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* bar   = stack->add(std::make_unique<ui::InfoBarControl>("Offline", "Changes will sync later.",
                                                           ui::InfoBarSeverity::Warning, true));
bar->on_closing([](const ui::PopupClosingArgs& args) {
    return args.reason == ui::PopupCloseReason::Programmatic ? ui::Cancel : ui::Proceed; // keep it open
});
bar->set_action_button_content(std::make_unique<ui::ButtonControl>("Retry"))->on_click([] { save(); });

ui::InfoBar

An inline status banner. Builds a ui::InfoBarControl. Closed by default, matching the control.

The handlers are installed before is_open is bound, so a bound is_open flipping back to false raises .on_closing/.on_closed like any other close.

Example:

ui::Property<bool> update_ready{true};

window.set_content(ui::InfoBar{
    .title         = "Update available",
    .message       = "Restart to install.",
    .is_open       = update_ready, // two-way: closing the bar writes false
    .severity      = ui::InfoBarSeverity::Success,
    .action_button_content = ui::Button{.text = "Restart", .on_click = [&] { restart_app(); }},
});

Every field, in the order a designated initializer names them:

ui::InfoBar{
    .title, .message, .is_open, .severity, .closable, .icon_visible, .style, .margin, .width,
    .height, .min_width, .min_height, .max_width, .max_height, .horizontal_alignment,
    .vertical_alignment, .visible, .tool_tip, .enabled, .accessibility, .on_close_button_click,
    .on_closing, .on_closed, .on_pointer_entered, .on_pointer_exited, .on_got_focus,
    .on_lost_focus, .on_key_down, .on_wheel, .control, .action_button_content, .content
}

Fields, in declaration order (designators must follow it):

Field Type Default
title ui::Binding<std::string> The bold title, first on the line.
message ui::Binding<std::string> The message after the title.
is_open ui::TwoWayField<bool> {false} A closed bar takes no room. ui::bind(prop) is two-way: closing the bar writes false into the property, and a false that on_closing cancels is put back to true.
severity ui::Binding<ui::InfoBarSeverity> {ui::InfoBarSeverity::Informational} Picks the background color and the status icon.
closable ui::Binding<bool> {true} Shows the close button.
icon_visible ui::Binding<bool> {true} Shows the severity icon.
on_close_button_click ui::Action The close button was clicked, before .on_closing.
on_closing ui::Callback<ui::Decision(const ui::PopupClosingArgs&)> Why it is about to close; return ui::Cancel to keep it open.
on_closed ui::Callback<void(ui::PopupCloseReason)> The bar has closed, and why.
on_pointer_entered ui::Action The pointer moved onto the control.
on_pointer_exited ui::Action The pointer left the control.
on_got_focus ui::Action Keyboard focus arrived on the control, or on anything inside it, from outside it. A control with nothing focusable in it never gets focus, and never raises this.
on_lost_focus ui::Action Keyboard focus left the control and everything inside it.
on_key_down ui::Callback<ui::Handling(const ui::KeyEvent&)> A key pressed while focus is on the control or inside it, before the control's own handling; ui::Handled stops it there (Element::on_key_down()).
on_wheel ui::Callback<ui::Handling(const ui::PointerEvent&)> A wheel turn over the control, before the control scrolls; ui::Handled stops it there (Element::on_wheel()).
control ui::ControlOut<ui::InfoBar> Out: the handle that receives the built control.
action_button_content ui::Spec A button placed after the message, usually a ui::Button, with ButtonVariant::Hyperlink for a link.
content ui::Spec Custom content on a row of its own below the title, message and action (in their place when all three are empty), across the full width up to the close button.

Plus the common fields style, margin, width, height, min_width, min_height, max_width, max_height, horizontal_alignment, vertical_alignment, visible, tool_tip, enabled, accessibility every spec carries (conventions).

build

std::unique_ptr<Element> build()&&

Consumes the spec and returns the built ui::InfoBarControl; the caller owns it.

ui::InfoBarControl

Derives from ui::Element.

An inline, closable banner that shows an app-wide status message with a severity color and icon.

A freshly built bar is closed: it takes no room and draws nothing until set_open(true). Title, message and the optional action button sit on one line when they fit and stack (wrapping at whole words) when they don't; the bar is at least 48 DIPs tall. Optional custom content (set_content()) gets a row of its own below them. The InfoBar itself is never a tab stop. Its action button, its content's controls and its close button are.

Closing runs in a fixed order: a close-button click first raises on_close_button_click(), then on_closing() (return ui::Cancel to keep it open, leaving is_open() true). Only a close that goes ahead flips is_open() to false and raises on_closed(). set_open(false) runs the same on_closing() and on_closed() sequence with reason Programmatic. Reopening raises nothing.

Example:

// Declarative, with the open state in a Property:
ui::Property<bool> open{true};
window.set_content(ui::InfoBar{
    .title     = "Update available",
    .message   = "Restart the app to apply the update.",
    .is_open   = open,
    .severity  = ui::InfoBarSeverity::Success,
    .on_closed = [&open](ui::PopupCloseReason) { open = false; },
    .action_button_content = ui::Button{.text = "Restart", .on_click = [] { restart_app(); }},
});

// Imperative:
auto  stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
auto* bar   = stack->add(std::make_unique<ui::InfoBarControl>("Offline", "Changes will sync later.",
                                                           ui::InfoBarSeverity::Warning, true));
bar->on_closing([](const ui::PopupClosingArgs& args) {
    return args.reason == ui::PopupCloseReason::Programmatic ? ui::Cancel : ui::Proceed; // keep it open
});
bar->set_action_button_content(std::make_unique<ui::ButtonControl>("Retry"))->on_click([] { save(); });

InfoBarControl

InfoBarControl()

A closed bar, which takes no room and draws nothing until opened.

InfoBarControl

InfoBarControl(std::string title, std::string message, InfoBarSeverity severity = InfoBarSeverity::Informational, bool is_open = false)

A bar with its title, message and severity set, open or (by default) closed.

title

const std::string& title() const

The bold title, first on the line; empty by default.

set_title

void set_title(std::string title)

Sets the title (UTF-8). Updates the layout.

message

const std::string& message() const

The message after the title, wrapped at whole words when the bar stacks.

set_message

void set_message(std::string message)

Sets the message (UTF-8). Updates the layout.

severity

InfoBarSeverity severity() const

The severity; Informational by default.

set_severity

void set_severity(InfoBarSeverity severity)

Sets the severity, changing the background and icon; redraws.

is_icon_visible

bool is_icon_visible() const

Whether the severity icon shows at the left; true by default.

set_icon_visible

void set_icon_visible(bool visible)

Shows or hides the severity icon. Updates the layout.

is_open

bool is_open() const

Whether the bar shows; false by default.

set_open

void set_open(bool is_open)

Setting false runs the closing sequence, which on_closing() can cancel, with reason Programmatic. Setting true always reopens. Does nothing, and raises nothing, if the value is unchanged.

is_closable

bool is_closable() const

Whether the close button shows; true by default.

set_closable

void set_closable(bool closable)

Shows/hides the owned close button; true by default.

enabled

bool enabled() const

A disabled bar grays out its close button, which then takes no input. The action button and the content keep their own state.

set_action_button_content

template <typename T>
T* set_action_button_content(std::unique_ptr<T> action)

Takes ownership of the action element (normally a Button, or one with ButtonVariant::Hyperlink) and returns a non-owning observer. It sits after the message.

action_button_content

Element* action_button_content() const

The action element (non-owning), or nullptr.

clear_action_button_content

void clear_action_button_content()

Removes and destroys the action element. Updates the layout.

set_content

template <typename T>
T* set_content(std::unique_ptr<T> content)

Takes ownership of custom content and returns a non-owning observer; a null content clears it. The content gets the full width between the icon and the close button, on its own row below the title, message and action. With no title, message or action it moves up into their row instead, centered against the icon and close button. The bar never stacks or wraps it as it does the message. The content lays itself out in the width it is given.

content

Element* content() const

The custom content (non-owning), or nullptr.

clear_content

void clear_content()

Removes and destroys the custom content. Updates the layout.

on_close_button_click

void on_close_button_click(Callback<void()> handler)

Fired on every close-button click, before on_closing(), whether or not the close is then canceled.

on_closing

void on_closing(Callback<Decision(const PopupClosingArgs&)> handler)

Runs before is_open() flips to false. Returning ui::Cancel keeps the bar open, and is_open() stays true throughout.

on_closed

void on_closed(Callback<void(PopupCloseReason)> handler)

Fired once a close goes ahead, that is when on_closing() did not cancel it.

close_button_bounds

const Rect& close_button_bounds() const

The close button's own rect from the most recent arrange(), for hit-testing. Empty while the close button is hidden.

title_bounds

const Rect& title_bounds() const

The title's rect from the most recent arrange().

message_bounds

const Rect& message_bounds() const

The message's rect from the most recent arrange().

content_bounds

const Rect& content_bounds() const

The slot the custom content was last arranged into (before its own margin and alignment): below the title row, or the title row itself when the bar has no title, message or action. Empty without content.

is_vertical

bool is_vertical() const

Whether the last measure() stacked title, message and action.

for_each_child

void for_each_child(ChildVisitor visit) const override

Every owned child that currently takes part in input, focus and rendering, in tab order: the action, then the custom content, while open; the close button while open and closable.

automation_role

AutomationRole automation_role() const override

What screen readers and other assistive tools see of this node: the role, name, help text and children here, and what a client can do with the node through the providers automation_providers() lists (ui/Automation.hpp).

automation_role() is the role this node reports; Group by default.

automation_name_fallback

std::string automation_name_fallback() const override

automation_name()'s fallback when accessibility().name is empty. Default: no inherent name, correct for controls with no visible text of their own (Slider, ProgressBar), which need an explicit accessibility().name from the caller. A control with its own visible text (Button, CheckBox, TextControl, ...) overrides this to return it.

measure_override

Size measure_override(Size available, const MeasureContext& context) const override

At least 48 DIPs tall, taller when the content stacks (see is_vertical()) or custom content adds its row. Zero size while closed.

arrange_override

void arrange_override(const Rect& final_rect, const ArrangeContext& context) override

Position children within the rect arrange() settled on (also in bounds(), window DIPs). Default: nothing, for a leaf.

render_override

void render_override(Renderer& renderer, const RenderContext& context) const override

What the control draws, in layout coordinates; render() has already applied the visual layer. A container draws its children through their render(), never their render_override().

enabled_changed

void enabled_changed() override

is_enabled() flipped, through set_enabled() here or on an ancestor, or a move to another parent. Drop any press or hover state. The element is redrawn either way. No-op by default.

key_override

bool key_override(const KeyEvent& e) override

A key for this element: the focused one, or one inside it that did not handle it. Return true when the key did something here, and it goes no further; false lets it bubble on to the parent and then to the shortcuts, a dialog's default button and arrow-key focus moves. Default: false.

Enumerations

InfoBarSeverity

enum class InfoBarSeverity

How serious an InfoBar's message is; picks the bar's background color and its status icon.

Value
Informational neutral background, info icon (the default)
Success success background, check-mark icon
Warning caution background, warning icon
Error critical background, error icon

Tests

  • tests/test_info_bar.cpp