GPUI Kit's popover surface, with its arrow or without any surface, as Avalonia's Flyout.

Partial
InteractivePopover demo
<Panel MinWidth="320" MinHeight="200">
  <Button Classes="outline" Content="Open popover" HorizontalAlignment="Left" VerticalAlignment="Top">
    <Button.Flyout>
      <Flyout Placement="BottomEdgeAlignedLeft" PlacementConstraintAdjustment="SlideX, SlideY" FlyoutPresenterClasses="arrow">
        <StackPanel Spacing="4" Width="240">
          <TextBlock Text="Dimensions" FontWeight="SemiBold" />
          <TextBlock Text="Set the dimensions for the layer." Foreground="{DynamicResource Gpui.MutedForeground}" TextWrapping="Wrap" />
        </StackPanel>
      </Flyout>
    </Button.Flyout>
  </Button>
</Panel>

Usage

The theme covers Flyout and FlyoutPresenter: the popover background on the theme radius, a 1px ring and GPUI Kit's shadow, about 12px of padding, and a 4px gap from the trigger on whichever side the flyout opens. GPUI Kit never flips a popover, so give every flyout PlacementConstraintAdjustment="SlideX, SlideY"; an offset of n in GPUI Kit is a HorizontalOffset or VerticalOffset of n − 4, as the theme adds the gap. The popover opens in place, as GPUI Kit's does.

GPUI Kit's anchors map to Placement as follows.

GPUI Kit anchorPlacement
TopLeftBottomEdgeAlignedLeft
TopCenterBottom
TopRightBottomEdgeAlignedRight
BottomLeftTopEdgeAlignedLeft
BottomCenterTop
BottomRightTopEdgeAlignedRight
LeftCenterRight
RightCenterLeft

FlyoutPresenterClasses picks the look: arrow adds GPUI Kit's 6px arrow toward the trigger (the gap grows by its depth), and plain is appearance(false): no surface and no padding, only the content.

Examples

The eight placements; each slides to stay on screen instead of flipping.

Placements
InteractivePopover demo: Placements
<Panel MinWidth="640" MinHeight="300">
  <Grid ColumnDefinitions="Auto,Auto,Auto" RowDefinitions="Auto,Auto,Auto" ColumnSpacing="8" RowSpacing="8"
        HorizontalAlignment="Center" VerticalAlignment="Center">
    <Button Classes="outline" Content="Top start" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="TopEdgeAlignedLeft" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
    <Button Grid.Column="1" Classes="outline" Content="Top" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="Top" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
    <Button Grid.Column="2" Classes="outline" Content="Top end" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="TopEdgeAlignedRight" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
    <Button Grid.Row="1" Classes="outline" Content="Left" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="Left" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
    <Button Grid.Row="1" Grid.Column="2" Classes="outline" Content="Right" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="Right" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
    <Button Grid.Row="2" Classes="outline" Content="Bottom start" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="BottomEdgeAlignedLeft" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
    <Button Grid.Row="2" Grid.Column="1" Classes="outline" Content="Bottom" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="Bottom" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
    <Button Grid.Row="2" Grid.Column="2" Classes="outline" Content="Bottom end" HorizontalAlignment="Stretch">
      <Button.Flyout>
        <Flyout Placement="BottomEdgeAlignedRight" PlacementConstraintAdjustment="SlideX, SlideY" Content="Popover content" />
      </Button.Flyout>
    </Button>
  </Grid>
</Panel>

plain draws the content alone; here an Alert brings its own surface.

Plain
InteractivePopover demo: Plain
<Panel MinWidth="360" MinHeight="180">
  <Button Classes="outline" Content="Open plain popover" HorizontalAlignment="Left" VerticalAlignment="Top">
    <Button.Flyout>
      <Flyout Placement="BottomEdgeAlignedLeft" PlacementConstraintAdjustment="SlideX, SlideY" FlyoutPresenterClasses="plain">
        <gpui:Alert Classes="info" Title="No surface" Content="A plain popover draws only its content." Width="300" />
      </Flyout>
    </Button.Flyout>
  </Button>
</Panel>

Not covered

  • The closing animation; a closed popup cannot be drawn in Avalonia.