Floating panel anchored to a trigger, for rich content such as filters, a mini profile or an explanation. A click trigger toggles it; trigger-on="hover" turns it into a hover card that also opens on keyboard focus. Reach for it when a tooltip is too small and a dialog too much, and with flush to open a sui-menu.
import { Component } from "@angular/core";
import { SuiPopover } from "@shineui/angular";
@Component({
standalone: true,
imports: [SuiPopover],
template: `<sui-popover width="280" [(open)]="open" (suiClose)="onChange($event)"><sui-button slot="trigger" variant="outline" label="Aging" icon="fa-solid fa-chevron-down" icon-pos="end"></sui-button>
<div style="font-size:12.5px;line-height:1.7">
<div style="display:flex;justify-content:space-between"><span>Current</span><b style="font-feature-settings:'tnum'">$18,240.00</b></div>
<div style="display:flex;justify-content:space-between"><span>1 to 30 days</span><b style="font-feature-settings:'tnum'">$6,420.00</b></div>
<div style="display:flex;justify-content:space-between"><span>31 to 60 days</span><b style="font-feature-settings:'tnum'">$12,480.00</b></div>
</div></sui-popover>`,
})
export class Example {
open = false;
onChange(e: CustomEvent) { console.log(e.detail); }
}
Basic
The first focusable in the trigger slot gets aria-haspopup="dialog", aria-expanded and aria-controls. A click opens a role="dialog" panel and moves focus onto it, so the role and the content are announced; an outside click closes it.
open pins the panel from the host without moving focus. position is the preferred side, and the panel flips to the other one when the viewport has no room. While open the panel paints in the top layer, so a sticky toolbar or a transformed card cannot cover or displace it.
align picks the trigger edge the panel lines up with, above or below it. start, the default, and end follow the reading direction, so the panel opens from the leading edge under dir="rtl" too; left and right name sides of the screen in either direction, as position does. The split button takes the same four.
Lined up with the leading edge.
Lined up with the trailing edge.
<div style="min-height:210px;display:flex;justify-content:space-between;gap:20px">
<sui-popover open width="220" align="start">
<sui-button slot="trigger" variant="outline" label="Start" icon="fa-solid fa-chevron-down" icon-pos="end"></sui-button>
<div style="font-size:12.5px;color:var(--ink-muted)">Lined up with the leading edge.</div>
</sui-popover>
<sui-popover open width="220" align="end">
<sui-button slot="trigger" variant="outline" label="End" icon="fa-solid fa-chevron-down" icon-pos="end"></sui-button>
<div style="font-size:12.5px;color:var(--ink-muted)">Lined up with the trailing edge.</div>
</sui-popover>
</div>
Hover cards
A hover card opens after open-delay and hides close-delay after the pointer leaves; keyboard focus opens it at once, so Tab to the link, and a card that holds focus stays up until focus leaves it. hover-persist keeps the second card up until an outside click.
flush drops the inner padding, so a sui-menu or sui-list runs to the edge of the card. menu makes the trigger a menu button: it announces a menu, opening focuses the first row so the arrows work at once, and the panel has no dialog role. A suiPick listener closes it and focus returns to the trigger.
suiOpen fires when a trigger opens the panel, and the cancelable suiClose fires before it closes and says why: escape, outside or trigger, where outside also covers Tab leaving the panel and trigger covers a hover card going away on mouse-out. preventDefault on suiClose keeps the panel open.
On a button trigger, opens or closes a click panel. With menu, opening puts focus on the first row.
ArrowDownArrowUp
On the trigger of a menu popover, opens it with focus on the first or the last row, and moves focus into an open one the same way. Inside, the arrows are the menu's own.
Tab
Focus landing on a hover trigger opens its card at once; focus leaving it hides the card after close-delay unless hover-persist is set. Inside a click panel, Tab past the last control closes it and carries on to the control after the trigger; Shift+Tab before the first lands on the trigger.
Escape
Closes the panel and returns focus to the trigger. Inside a dialog the popover takes the key first and the dialog stays; a select list open inside the panel takes it before the popover.
API
<sui-popover>
Properties
Property
Attribute
Type
Default
Description
align
align
"end" | "left" | "right" | "start"
'start'
Which trigger edge the panel lines up with, above or below it; a panel placed to the left or right centers on the trigger instead. start and end follow the reading direction, and start is the default, so the panel opens from the trigger's leading edge under dir="rtl" too; left and right name sides of the screen in either direction, as position does. The same four values as the split button's menuAlign.
closeDelay
close-delay
number
200
Grace period in ms before a hover card hides after mouse-out.
flush
flush
boolean
false
Drops the panel's inner padding. The panel is padded by default, for prose, fields and cards. Set flush when the panel hosts a list that draws its own row inset, a sui-menu or sui-list, so the rows run edge to edge and the panel is the one and only card around them. Same prop as sui-card.
hoverPersist
hover-persist
boolean
false
Keep a hover card open after mouse-out until an outside click.
menu
menu
boolean
false
The panel holds a sui-menu, so the trigger is a menu button: it announces a menu (aria-haspopup="menu"), opening it from the trigger by click, Enter, Space or ArrowDown puts focus on the first row, ArrowUp on the last, and the arrows, Home, End and typeahead are the menu's own from there. The panel carries no dialog role, since the menu's role="menu" is the surface a reader hears, and Escape or Tab closes it and hands focus back to the trigger, as on every click panel. Pair it with flush. A hover card ignores it.
open
open
boolean
false
Shows the panel (the reference defaultOpen). Mutable; the element opens and closes itself. A panel pinned this way leaves focus where it is; only a trigger gesture moves focus into it. When the panel closes, a popup still open inside it, a select's list or a menu, closes with it and asks through its own suiClose with reason outside.
openDelay
open-delay
number
350
Hover open delay in ms. Keyboard focus opens a hover card immediately.
position
position
"bottom" | "left" | "right" | "top"
'bottom'
Preferred side of the trigger; the panel is position: fixed 8px off it and flips to the opposite side when the viewport has no room.
triggerOn
trigger-on
"click" | "hover"
'click'
click (default) toggles on click and opens a role="dialog" panel that takes focus; hover opens a hover card, which also opens on keyboard focus and closes when focus leaves the trigger and the panel together.
Fires before the panel closes itself; detail is 'escape' | 'outside' | 'trigger' ('trigger' covers both a trigger click and a hover card's mouse-out or blur; 'outside' covers an outside pointer and focus leaving a click panel on Tab). Cancelable: preventDefault() keeps it open. It does not bubble, so a dialog around the popover never hears it.
suiOpen
void
onSuiOpen
@sui-open
Fires when an interaction opens the panel. It does not bubble.
Slots
Slot
Description
(default)
Panel content.
trigger
The element that opens the panel (a sui-button, link or text).
Types
SuiCloseReasontypeWhy a dismissible surface is closing. Detail of the cancelable suiClose. A consumer expresses "a stray backdrop click must not close this" by calling preventDefault() on the reason it does not accept, which is why none of these needs a prop of its own.
No members.
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.