Popover
Component

Popover

A floating content panel that appears next to a trigger element, commonly used for tooltips, dropdowns, and informational overlays.

Demo

Features

  • Flexible positioning with collision detection
  • Optional overlay backdrop
  • Focus trapping support
  • Close button component
  • Controlled and uncontrolled modes
  • WCAG compliant with proper ARIA attributes

Installation

bash
dotnet add package SummitUI

Anatomy

Import the components and structure them as follows:

razor
<SmPopoverRoot>
    <SmPopoverTrigger class="su-popover-trigger">Open</SmPopoverTrigger>
    <SmPopoverPortal>
        <SmPopoverContent class="su-popover-content">
            <p>Popover content</p>
            <SmPopoverClose class="su-popover-close">Close</SmPopoverClose>
        </SmPopoverContent>
    </SmPopoverPortal>
</SmPopoverRoot>

Sub-components

PopoverRoot

Root container managing popover state.

PopoverTrigger

Button that toggles the popover.

PopoverPortal

Renders content in fixed-position container.

PopoverContent

Floating content panel with positioning.

PopoverOverlay

Optional backdrop overlay.

PopoverClose

Close button within popover.

API Reference

PopoverRoot

Property Type Default Description
Open bool? null Controlled open state
DefaultOpen bool false Default open state (uncontrolled)
OpenChanged EventCallback<bool> - Open state change callback
OnOpen EventCallback - Callback when popover opens
OnClose EventCallback - Callback fired immediately when close is triggered (before animations start)
Modal bool false Whether to trap focus

PopoverContent

Property Type Default Description
Side Side Bottom Placement side
SideOffset int 0 Offset from trigger (px)
Align Align Center Alignment along side axis
AvoidCollisions bool true Avoid viewport boundaries
TrapFocus bool false Whether to trap focus
EscapeKeyBehavior EscapeKeyBehavior Close Escape key behavior
OutsideClickBehavior OutsideClickBehavior Close Outside click behavior
OnOpenAutoFocus EventCallback - Callback fired after popover opens and receives focus
OnCloseAutoFocus EventCallback - Callback fired after close animations complete and focus returns to trigger

Examples

Basic Popover

razor
<SmPopoverRoot>
    <SmPopoverTrigger class="su-popover-trigger">Click me</SmPopoverTrigger>
    <SmPopoverPortal>
        <SmPopoverContent class="su-popover-content" SideOffset="8">
            <h3 class="su-popover-title">Basic Popover</h3>
            <p class="su-popover-description">This is a simple popover with some content.</p>
            <SmPopoverClose class="su-popover-close">Close</SmPopoverClose>
        </SmPopoverContent>
    </SmPopoverPortal>
</SmPopoverRoot>

With Overlay

Add a backdrop overlay for modal-like behavior.

razor
<SmPopoverRoot>
    <SmPopoverTrigger class="su-popover-trigger">Open with Overlay</SmPopoverTrigger>
    <SmPopoverPortal>
        <SmPopoverOverlay class="su-popover-overlay" />
        <SmPopoverContent class="su-popover-content" SideOffset="8">
            <h3 class="su-popover-title">Modal-like Popover</h3>
            <p class="su-popover-description">Click the overlay or press Escape to close.</p>
            <SmPopoverClose class="su-popover-close">Done</SmPopoverClose>
        </SmPopoverContent>
    </SmPopoverPortal>
</SmPopoverRoot>

Different Positions

Position the popover on different sides.

razor
@* Bottom (default) *@
<SmPopoverContent class="su-popover-content" Side="Side.Bottom" SideOffset="8">
    Content appears below
</SmPopoverContent>

@* Top *@
<SmPopoverContent class="su-popover-content" Side="Side.Top" SideOffset="8">
    Content appears above
</SmPopoverContent>

@* Left *@
<SmPopoverContent class="su-popover-content" Side="Side.Left" SideOffset="8">
    Content appears to the left
</SmPopoverContent>

@* Right *@
<SmPopoverContent class="su-popover-content" Side="Side.Right" SideOffset="8">
    Content appears to the right
</SmPopoverContent>

Controlled Mode

Control the open state externally.

razor
@code {
    private bool isOpen = false;
}

<SmPopoverRoot Open="@isOpen" OpenChanged="@(v => isOpen = v)">
    <SmPopoverTrigger class="su-popover-trigger">
        @(isOpen ? "Close" : "Open")
    </SmPopoverTrigger>
    <SmPopoverPortal>
        <SmPopoverContent class="su-popover-content" SideOffset="8">
            <p>Controlled popover content</p>
        </SmPopoverContent>
    </SmPopoverPortal>
</SmPopoverRoot>

<button class="su-button" @onclick="@(() => isOpen = !isOpen)">
    Toggle Externally
</button>

Callback Timing with Animations

The popover fires callbacks at different points during the open/close sequence.

Callback Location When it fires
OnClose PopoverRoot Immediately when close is triggered (before animations start)
OnCloseAutoFocus PopoverContent After all close animations complete and focus returns to trigger

When to use each

  • OnClose: Use for immediate state updates, analytics, or when animation timing doesn't matter
  • OnCloseAutoFocus: Use when you need to ensure the popover is fully closed (e.g., cleanup or showing a toast after the popover disappears)

Styling

Data Attributes

Attribute Values Description
data-state "open" | "closed" Popover open state
data-side "top" | "right" | "bottom" | "left" Current placement side
data-align "start" | "center" | "end" Current alignment

CSS Example

css
/* Trigger */
.su-popover-trigger {
    display: inline-flex;
    align-items: center;
    padding: 8px 16px;
    background: rgb(var(--su-primary));
    color: rgb(var(--su-primary-foreground));
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.su-popover-trigger[data-state="open"] {
    opacity: 0.9;
}

/* Overlay */
.su-popover-overlay {
    position: fixed;
    inset: 0;
    background: rgb(var(--su-foreground) / 0.4);
}

/* Content */
.su-popover-content {
    background: rgb(var(--su-card));
    border: 1px solid rgb(var(--su-border));
    border-radius: 8px;
    box-shadow: 0 4px 20px rgb(var(--su-foreground) / 0.15);
    min-width: 280px;
    max-width: 400px;
    padding: 16px;
}

.su-popover-content[data-state="closed"] {
    display: none;
}

Accessibility

Keyboard Navigation

Key Action
Enter / Space Toggle popover (on trigger)
Escape Close popover
Tab Move focus within popover (when focus trapped)

ARIA Attributes

  • Trigger: Has aria-haspopup="dialog" and aria-expanded
  • Content: Linked to trigger via aria-controls
  • Close: Has aria-label for screen readers

Focus Management

  • When opened, focus moves to the first focusable element in the content
  • When closed, focus returns to the trigger
  • Optional focus trapping keeps focus within the popover
An unhandled error has occurred. Reload X