Popover
Popover displays contextual information or actions in a floating container that appears relative to a trigger element. Unlike dialogs, popovers are non-modal and allow users to continue interacting with the background content.
import {PopoverModule} from "@qualcomm-ui/angular/popover"Examples
Simple
Basic popover using the simple API with a label and child content. The anchor and trigger are supplied using directives, while the content is the default slot.
<div description="Description" label="Label" q-popover>
<div q-popover-anchor>
<button q-button q-popover-trigger variant="outline">Click Me</button>
</div>
</div>
Composite
Build with the composite API for granular control. This API requires you to provide each subcomponent, but gives you full control over the structure and layout.
<div q-popover-root>
<div q-popover-anchor>
<button q-button q-popover-trigger variant="outline">Click Me</button>
</div>
<ng-template qPortal>
<div q-popover-positioner>
<div q-popover-content>
<div q-popover-arrow></div>
<div q-popover-label>Label</div>
<div q-popover-description>Description</div>
</div>
</div>
</ng-template>
</div>
Emphasis
Use emphasis to control the visual style of the popover. Two emphasis options are available: neutral (default) and brand.
import {Component} from "@angular/core"
import {PortalDirective} from "@qualcomm-ui/angular-core/portal"
import {ButtonModule} from "@qualcomm-ui/angular/button"
import {PopoverModule} from "@qualcomm-ui/angular/popover"
import type {QdsPopoverEmphasis} from "@qualcomm-ui/qds-core/popover"
@Component({
imports: [PopoverModule, ButtonModule, PortalDirective],
selector: "popover-emphasis-demo",
template: `
<div class="flex gap-4">
@for (emp of emphasisOptions; track emp) {
<div q-popover-root [emphasis]="emp">
<div q-popover-anchor>
<button emphasis="primary" q-button q-popover-trigger>
{{ emp }}
</button>
</div>
<ng-template qPortal>
<div q-popover-positioner>
<div q-popover-content>
<div q-popover-arrow></div>
<div q-popover-label>Label</div>
<div q-popover-description>This is a {{ emp }} popover.</div>
</div>
</div>
</ng-template>
</div>
}
</div>
`,
})
export class PopoverEmphasisDemo {
readonly emphasisOptions: QdsPopoverEmphasis[] = ["neutral", "brand"]
}Explorer
Component Anatomy
Hover to highlight, click to view API
API
q-popover
The q-popover directive extends the q-popover-root directive with the following props:
stringbooleanbooleanstringComposite API
This section describes the elements of the Popover's composite API.
q-popover-root
booleanbooleanbooleanboolean'ltr' | 'rtl'
| 'neutral'
| 'brand'
() =>
| Node
| ShadowRoot
| Document
() => HTMLElement
booleantrue:- interaction with outside elements will be disabled
- only popover content will be visible to screen readers
- scrolling is blocked
- focus is trapped within the popover
booleanArray<
() => Element
>
- should not have pointer-events disabled
- should not trigger the dismiss event
PositioningOptionsbooleanKeyboardEventCustomEvent<{
event?: E
}>
| CustomEvent<{event?: E}>
| CustomEvent<{event?: E}>
{
open: boolean
}
CustomEvent<{
event?: E
}>
CustomEvent<{
originalIndex: number
originalLayer: HTMLElement
targetIndex: number
targetLayer: HTMLElement
}>
data-popover-part'root'q-popover-anchor
stringdata-popover-part'anchor'q-popover-trigger
stringdata-placement| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
data-popover-part'trigger'data-state| 'open'
| 'closed'
q-popover-positioner
stringdata-popover-part'positioner'styleq-popover-content
stringclass'qui-popover__content'data-emphasis| 'neutral'
| 'brand'
data-expandeddata-placement| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
data-popover-part'content'data-state| 'open'
| 'closed'
hiddenbooleantabIndex-1
q-popover-arrow
stringclass'qui-popover__arrow'data-emphasis| 'neutral'
| 'brand'
data-popover-part'arrow'styleq-popover-arrow-tip
data-popover-part'arrow-tip'styleq-popover-label
stringdata-popover-part'label'q-popover-description
stringdata-popover-part'description'q-popover-close-trigger
stringdata-popover-part'close-trigger'Data Structures
PopoverPositioningOptions
numberstring[data-menu-part=arrow]).() =>
| 'clippingAncestors'
| Element
| Array<Element>
| {
height: number
width: number
x: number
y: number
}
boolean| boolean
| Array<
| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
>
(
element:
| HTMLElement
| VirtualElement,
) => {
height?: number
width?: number
x?: number
y?: number
}
numberboolean| boolean
| {
ancestorResize?: boolean
ancestorScroll?: boolean
animationFrame?: boolean
elementResize?: boolean
layoutShift?: boolean
}
{
crossAxis?: number
mainAxis?: number
}
(
data: ComputePositionReturn,
) => void
(data: {
placed: boolean
}) => void
numberboolean| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
booleannumberboolean| 'absolute'
| 'fixed'
(data: {
updatePosition: () => Promise<void>
}) => void | Promise<void>