Skip to content

Window and system UI

WindowOptions is stable for one runtime. It sets title, initial logical size, content mode, chrome mode, preferred custom title-bar height, and caption labels.

WindowContentMode::SafeArea keeps root content inside platform obstructions. EdgeToEdge gives the app the complete drawing surface; apply SafeAreaPadding only where content must avoid selected edges.

return Content().With(
SafeAreaPadding{.top = true, .right = true, .bottom = true, .left = true},
SystemBarsAppearance{
.status_bar_background = theme.colors.primary,
.status_bar_content = SystemBarContentBrightness::Light,
}
);

In SafeArea mode the runtime consumes physical safe-area insets before measuring the root. In EdgeToEdge mode the root receives the complete viewport and can apply selected insets to individual surfaces instead of padding the entire application.

Software-keyboard viewport changes are distinct from persistent safe-area insets.

Choose the mode once from product intent. Use SafeArea for conventional document and form surfaces that never draw behind system UI. Use EdgeToEdge when a background, image, map, or shell should reach the physical edge, then apply SafeAreaPadding to the specific controls and readable content that must remain unobstructed. Do not add manual status-bar constants; consume the adapter-provided inset in logical units.

SystemBarsAppearance sets available status-bar and navigation-bar backgrounds and chooses automatic, light, or dark system content. Use automatic brightness when the adapter can infer it from the resolved background; set an explicit value when the application owns a contrasting surface.

System bar availability varies by mobile platform and window mode. Unsupported fields remain platform-neutral intent rather than emulated desktop bars.

System-bar appearance is declarative and follows the mounted surface that supplies it. Keep background and content brightness in the same modifier so a theme or route change cannot briefly produce unreadable system icons. Automatic brightness is a convenience, not an accessibility guarantee; verify contrast on the actual system-bar treatment used by each mobile platform.

Desktop windows default to WindowChromeMode::System. Custom lets application UI occupy the title-bar surface; compose WindowTitleBar and use UseWindow() for window commands.

WindowTitleBar separates draggable and interactive regions while caption controls invoke the same WindowHandle commands as application controls. Custom caption height comes from WindowOptions; choose it to match the application’s shell rather than assuming one system height.

Custom chrome makes the entire top surface application UI. Mark only non-interactive drag regions, keep buttons and text fields outside those regions, and provide localized WindowCaptionLabels for the built-in caption actions. Window commands are requests to the current platform window; an embedded host may not support every operation.

Test custom chrome at normal and maximized sizes, multiple DPI values, all resize edges, keyboard focus, double-click maximize, and screen-reader navigation. macOS traffic-light geometry and Linux window-manager behavior are not Windows caption geometry, so keep platform reservations in WindowTitleBarMetrics rather than hard-coded layout constants.

WindowMetrics is an environment value containing viewport, remaining safe-area insets, and optional title-bar metrics. System-bar brightness can be automatic, light, or dark. Availability and native behavior vary by platform; see the platform guides.

Responsive composition should normally use UseViewportClass(). Read complete metrics only when geometry such as an edge surface or custom title bar genuinely depends on the exact viewport or remaining insets.

The platform may reduce the viewport when the input method appears. That is a window-metrics change, not a new safe-area edge and not a reason to permanently pad the root. Scrollable text-editing surfaces should let HuxerUI bring the active caret into view while preserving user-driven scroll behavior.

Validate focused fields near every edge, keyboard dismissal, orientation/resize, and transitions between hardware and software keyboards on the target device.

See the Window API and the relevant platform guide.

WindowHandle::Show(), Hide(), and Activate() control window visibility separately from application lifetime. OnCloseRequest and OnMinimizeRequest install lifecycle-bound decision handlers: true consumes the request, false lets the platform continue. Do not implement “minimize to tray” unless a usable tray presentation is available.

#include <huxerui/huxerui.h>
using namespace huxerui;
[[huxerui::composable]]
View TrayShell(ImageResource icon) {
auto application = UseApplication();
auto window = UseWindow();
auto tray = application.SystemTray();
tray.OnActivate([window] { window.Activate(); });
window.OnCloseRequest([window, tray] {
if (!tray.IsAvailable()) {
return false;
}
window.Hide();
return true;
});
Lifecycle([application, tray, icon] {
tray.Show(icon, {
.tooltip = "Document workspace",
.menu = {MenuItem("Quit", [application] { application.Quit(); })},
});
return [tray] { tray.Hide(); };
}, icon);
return Text("Workspace");
}

Pass a packaged raster image resource; tray icons must resolve to ImageAsset. The example uses an explicit Quit command, so hiding the last window does not make the application impossible to exit. One Runtime owns one active tray presentation and one committed activation handler.

Tray availability depends on the host, especially Linux desktop status-item support. Mobile and browser applications need a normal in-app entry point instead. WindowOptions::minimum_size requests a desktop minimum client size; it does not clamp actual WindowMetrics or pretend a mobile viewport is larger.