Skip to content

PopupStack

Namespace: Hex1b

Assembly: Hex1b.dll

Manages a stack of popups for menu-like overlay behavior. Each popup has a transparent backdrop - clicking the backdrop pops that layer.

csharp
public sealed class PopupStack

Inheritance

ObjectPopupStack

Properties

Count

Gets the number of popups currently open.

Returns: Int32

csharp
public int Count { get; }

HasPopups

Gets whether any popups are currently open.

Returns: Boolean

csharp
public bool HasPopups { get; }

Methods

BuildWidgets<TParent>(WidgetContext<TParent>)

Builds the ZStack widgets for all popups in the stack. Each popup is wrapped in a transparent Backdrop that calls PopToBarrier() when clicked. Anchored popups are positioned relative to their anchor node.

Parameters:

  • ctx (WidgetContext<<TParent>>): The widget context (typically from a ZStack).

Returns: IEnumerable<Hex1bWidget>

An enumerable of backdrop widgets for the popup stack.

csharp
public IEnumerable<Hex1bWidget> BuildWidgets<TParent>(WidgetContext<TParent> ctx) where TParent : Hex1bWidget

Clear()

Clears all popups from the stack, invoking OnDismiss callbacks for each. Focus is restored to the first (bottommost) popup's FocusRestoreNode if set.

csharp
public void Clear()

Pop()

Removes the topmost popup from the stack.

Returns: Boolean

True if a popup was removed, false if stack was empty.

csharp
public bool Pop()

Pop(out Hex1bNode?)

Removes the topmost popup from the stack and returns the node that should receive focus.

Parameters:

  • focusRestoreNode (Hex1bNode): The node that was designated to receive focus when this popup was pushed, or null.

Returns: Boolean

True if a popup was removed, false if stack was empty.

csharp
public bool Pop(out Hex1bNode? focusRestoreNode)

PopAtPosition(int, int)

Removes popups from the stack, stopping if the click position falls within content bounds of a lower layer (not just its backdrop).

Parameters:

  • x (Int32): The X coordinate of the click (screen position), or -1 to skip position check.
  • y (Int32): The Y coordinate of the click (screen position), or -1 to skip position check.

Returns: Boolean

True if any popups were removed, false if stack was empty.

csharp
public bool PopAtPosition(int x, int y)

PopToBarrier()

Removes popups from the stack until a barrier is reached or the stack is empty.

Returns: Boolean

True if any popups were removed, false if stack was empty.

csharp
public bool PopToBarrier()

Push(Func<Hex1bWidget>)

Pushes a new popup onto the stack (full-screen backdrop, not anchored).

Parameters:

  • contentBuilder (Func<Hex1bWidget>): A function that builds the widget content for the popup.

Returns: PopupEntry

The popup entry for optional fluent configuration (e.g., .AsBarrier()).

csharp
public PopupEntry Push(Func<Hex1bWidget> contentBuilder)

Push(Hex1bWidget)

Pushes a new popup onto the stack with static content (full-screen backdrop, not anchored).

Parameters:

  • content (Hex1bWidget): The widget content for the popup.

Returns: PopupEntry

The popup entry for optional fluent configuration (e.g., .AsBarrier()).

csharp
public PopupEntry Push(Hex1bWidget content)

PushAnchored(Hex1bNode, AnchorPosition, Func<Hex1bWidget>, Hex1bNode?, Action?)

Pushes an anchored popup positioned relative to a specific node. Automatically captures theme context from ancestor ThemePanelNodes.

Parameters:

  • anchorNode (Hex1bNode): The node to anchor the popup to.
  • position (AnchorPosition): Where to position the popup relative to the anchor.
  • contentBuilder (Func<Hex1bWidget>): A function that builds the widget content for the popup.
  • focusRestoreNode (Hex1bNode): Optional node to restore focus to when this popup is dismissed.
  • onDismiss (Action): Optional callback invoked when this popup is dismissed to clean up owner state.

Returns: PopupEntry

The popup entry for optional fluent configuration (e.g., .AsBarrier()).

csharp
public PopupEntry PushAnchored(Hex1bNode anchorNode, AnchorPosition position, Func<Hex1bWidget> contentBuilder, Hex1bNode? focusRestoreNode = null, Action? onDismiss = null)

PushAnchored(Hex1bNode, AnchorPosition, Hex1bWidget, Hex1bNode?, Action?)

Pushes an anchored popup positioned relative to a specific node.

Parameters:

  • anchorNode (Hex1bNode): The node to anchor the popup to.
  • position (AnchorPosition): Where to position the popup relative to the anchor.
  • content (Hex1bWidget): The widget content for the popup.
  • focusRestoreNode (Hex1bNode): Optional node to restore focus to when this popup is dismissed.
  • onDismiss (Action): Optional callback invoked when this popup is dismissed to clean up owner state.

Returns: PopupEntry

The popup entry for optional fluent configuration (e.g., .AsBarrier()).

csharp
public PopupEntry PushAnchored(Hex1bNode anchorNode, AnchorPosition position, Hex1bWidget content, Hex1bNode? focusRestoreNode = null, Action? onDismiss = null)

RemoveStaleAnchoredPopups()

Removes any popup entries whose anchor nodes are stale (have zero bounds). This happens when an anchor node is replaced during reconciliation but the popup still holds a reference to the old node. Call this after layout (Arrange) to clean up stale popups.

Returns: Boolean

True if any stale popups were removed.

csharp
public bool RemoveStaleAnchoredPopups()

Remarks

PopupStack is designed for cascading menus, dropdowns, and similar UX patterns where:

  • Multiple popups can be stacked (e.g., File → Recent Items → filename)
  • Each popup layer has its own transparent backdrop
  • Clicking a backdrop dismisses that layer (and propagates to layers below)

By default, clicking away from any popup clears the entire stack. To create a "barrier" that stops propagation (e.g., for modal dialogs), use :

csharp
e.Popups.Push(() => MyDialog()).AsBarrier();

Examples

csharp
// Simple popup (full-screen backdrop)
e.Popups.Push(() => BuildDialog());

// Anchored popup (positioned relative to triggering element)
e.Popups.PushAnchored(AnchorPosition.Below, () => BuildMenu());

// Barrier popup (stops cascade dismissal)
e.Popups.Push(() => BuildModal()).AsBarrier();

Released under the MIT License.