You can display web content that floats above a window's layout without shifting the panels beneath it. This works well for toasts, heads-up displays, in-window dialogs, command palettes, and dropdown menus.

Floating panels clip to the window frame. For menus and dropdown lists that need to extend outside the window, use [Popups and Dialogs](/docs/2.0/popups-and-dialogs) instead.

## Adding a Floating Panel

Call `Foreground::AddPanel()` on `Window::foreground()` to create a floating panel with a new View:

```cpp
#include <AppCore/Window.h>
#include <Ultralight/DOM.h>

using namespace ultralight;

class MyApp {
 public:
  void ShowHUD() {
    ///
    /// Float a small HUD 24px in from the window's top-left corner.
    ///
    hud_ = window_->foreground()->AddPanel({
        .width = "200px", .height = "120px", .placement = Anchor::At(24, 24) });
    hud_->view()->LoadHTML("<h1>Ultralight rocks!</h1>");
  }

  void OpenDropdown(dom::Element button);

 private:
  RefPtr<Window> window_;
  RefPtr<Panel> toolbar_;
  RefPtr<Panel> hud_;
  RefPtr<Panel> dropdown_;
  LayoutCallback on_dismiss_;
};
```

A floating panel is an ordinary `Panel` without a parent container— everything in [Laying Out Panels](/docs/2.0/laying-out-panels) applies.

### Setting Size and Visibility

Set `width` and `height` in `ForegroundPanelOptions` using logical pixels or a percentage of the window. Unset dimensions default to `100%`— passing empty options creates a panel that covers the entire window.

Set `hidden = true` to create the panel hidden. Call `Panel::Show()` once the page finishes loading to display it.

To configure the new View yourself, pass a `ViewConfig` as the second argument to `Foreground::AddPanel()`.

### Adopting an Existing View

Call `Foreground::AdoptPanel()` to float a View you already created. You can pass `ForegroundPanelOptions` as the optional second argument to set the panel's size and placement.

## Positioning with Anchors

The `placement` option takes an `Anchor` that determines where the floating panel sits inside the window:

| Form | Placement |
|---|---|
| `Anchor::At(x, y)` | Places the top-left corner at an absolute window position. |
| `Anchor::WindowCorner(corner)` | Snaps to a window corner and follows the window during resize. |
| `Anchor::WindowCenter()` | Centers the panel in the window and follows window resizes. |
| `Anchor::Fill()` | Places the panel at the window origin, filling the window when combined with default sizes. |
| `Anchor::Below(target, rect)` | Hangs the panel's top edge under a rectangle inside another panel. |

You can call `Offset(dx, dy)` on any anchor form to nudge the final position— for example, `Anchor::WindowCorner(AnchorCorner::BottomRight).Offset(-16, -16)` moves the panel inward from the bottom-right corner.

> 📘 Moving or Resizing Panels
>
> A floating panel's placement and size are fixed at creation. To move or resize a panel, keep a reference to its View with `Panel::view()` before calling `Foreground::Remove()`— `Panel::view()` returns null once the panel is removed. Pass that View to `Foreground::AdoptPanel()` with the new placement to keep the page loaded.

### Anchoring Below an Element

To anchor a floating panel to a DOM element in another panel, pass the element's bounding rectangle to `Anchor::Below()`:

```cpp
///
/// Open a dropdown under a button on the toolbar's page.
///
void MyApp::OpenDropdown(dom::Element button) {
  dom::DOMRect box = button.getBoundingClientRect();

  ///
  /// Hang the panel's top edge under the button with left edges aligned,
  /// flipping above the button when there is no room below.
  ///
  dropdown_ = window_->foreground()->AddPanel({
      .width = "240px", .height = "180px",
      .placement = Anchor::Below(toolbar_,
                                 Rect::FromXYWH(box.x, box.y, box.width,
                                                box.height))
                       .Align(AnchorAlign::Start)
                       .Fit(AnchorFit::Flip),
      .dismiss = Dismiss::Auto,
      .focus = FocusPolicy::Grab });
  dropdown_->view()->LoadURL("file:///dropdown.html");
}
```

The anchor rectangle uses the target panel's local logical pixels, which match the page's CSS pixels— so a bounding box from [Element Geometry and Scrolling](/docs/2.0/element-geometry-and-scrolling) passes straight through. The library re-derives this placement every frame as the target panel moves.

You can refine the placement with `Align()` (`AnchorAlign::Start`, `Center`, or `End`) and call `Fit(AnchorFit::Flip)` to flip the panel above the element when there isn't enough room below.

## Dismissing Automatically

Floating panels can close automatically when someone interacts with the window, behaving like native menus and dropdowns.

### Enabling Auto-Dismiss

Floating panels use `Dismiss::Manual` by default— they stay visible until you hide them.

Pass `dismiss = Dismiss::Auto` in `ForegroundPanelOptions` to enable automatic dismissal. The library hides the panel when:

- A mouse press occurs outside the panel.
- The user presses Esc.
- The window moves, resizes, minimizes, maximizes, or deactivates.
- The user presses the title bar or window frame edges.

Scrolling content inside the window does not dismiss the panel.

### Dismissal Behavior

Dismissing a floating panel hides it rather than destroying it— calling `Panel::Show()` brings it back.

The press that dismisses the panel is swallowed, so the page beneath never receives it.

### Reacting to Dismissals

Call `Panel::OnDismiss()` to respond when the library dismisses the panel:

```cpp
///
/// Fires only when the library dismissed the dropdown.
///
on_dismiss_ = dropdown_->OnDismiss([] {
  // The panel is already hidden; update application state here.
});
```

This callback fires only for automatic dismissals— calling `Panel::Hide()` yourself does not trigger it.

Keep the returned `LayoutCallback` alive for as long as the callback should fire. Destroying the object unregisters the callback.

## Managing Keyboard Focus

The `focus` option controls how a floating panel receives keyboard focus:

| Policy | Behavior |
|---|---|
| `FocusPolicy::Auto` | Focuses on click (the default). Showing the panel never takes keyboard focus. |
| `FocusPolicy::Grab` | Takes keyboard focus each time the panel is shown, even from inside a click handler. Suited for dropdowns, palettes, and in-window dialogs. |
| `FocusPolicy::None` | Never takes keyboard focus. Suited for toasts and heads-up displays. |

To focus a panel, call `Panel::Focus()` rather than `View::Focus()`, which ensures the window routes keyboard input properly. Calling `Panel::Focus()` on a hidden panel or a panel configured with `FocusPolicy::None` is ignored with a warning.

Hiding a focused floating panel releases keyboard focus— no panel holds focus until the user clicks one or you call `Panel::Focus()`.

## Stacking and Removing Panels

Floating panels stack in the order they're added, with the latest panel on top. Call `Panel::BringToFront()` to move a panel to the top of the floating layer— it receives mouse clicks first and paints last, on top of the others.

To remove a panel from the floating layer, call `Foreground::Remove()`. Dropping the panel handle does not remove it from the layer. If you hold a `RefPtr` to the panel's View, the View survives removal and can be adopted by another panel.
