Skip to main content
cngx-src documentation

CngxPopoverPanel

ComponentPrimaryOnPushNo encapsulationv0.1.0WCAG AA

projects/common/popover/popover-panel.component.ts

Import#

import { CngxPopoverPanel } from '@cngx/common/popover'

Description#

Rich popover panel molecule with header/body/footer slots, variant styling, arrow, close button, and content state templates.

Composes CngxPopover via hostDirectives - all popover inputs (placement, offset, closeOnEscape, mode, exclusive, cngxPopoverOpen) are forwarded.

The variant input is a free-form string mapped to a CSS class (cngx-popover-panel--{variant}). Five variants are pre-themed in popover-panel-theme.scss: default, info, warning, danger, success. Add custom variants via CSS.

Basic with header/body/footer

<button [cngxPopoverTrigger]="panel" (click)="panel.popover.toggle()">Menu</button>
<cngx-popover-panel #panel variant="danger" [showClose]="true" [showArrow]="true">
  <span cngxPopoverHeader>Delete Item?</span>
  <p cngxPopoverBody>This action cannot be undone.</p>
  <div cngxPopoverFooter>
    <cngx-popover-action role="dismiss">Cancel</cngx-popover-action>
    <cngx-popover-action role="confirm" [action]="delete" variant="danger">
      Delete
    </cngx-popover-action>
  </div>
</cngx-popover-panel>

With loading state

<cngx-popover-panel [loading]="isLoading()" [error]="loadError()">
  <p cngxPopoverBody>Loaded content here</p>
  <ng-template cngxPopoverLoading>Loading...</ng-template>
  <ng-template cngxPopoverError let-err>Failed: {{ err }}</ng-template>
</cngx-popover-panel>

https://cngxjs.github.io/cngx/examples/#/common/popover/popover-panel/content-states https://cngxjs.github.io/cngx/examples/#/common/popover/popover-panel/variants https://cngxjs.github.io/cngx/examples/#/common/popover/popover-panel/with-footer-actions

Metadata#

Host#

Providers#

CNGX_POPOVER_ARROW_BOUNDS
useExisting CngxPopoverPanel

Dependencies#

CngxPopoverinject()selfpopover

The underlying popover state machine.

Relationships

Index#

Inputs#

empty#
input()

Whether the panel content is empty. Fallback when [state] is not set.

default false
error#unknown
input()

Error value when content loading failed. Fallback when [state] is not set.

loading#
input()

Whether the panel content is in a loading state. Fallback when [state] is not set.

default false
input()

ARIA role applied to the panel host. Defaults to 'dialog' because the panel pairs aria-labelledby (header) with aria-describedby (body) - the standard dialog pattern. Override with 'alertdialog' for irrecoverable confirmations, 'tooltip' for passive callouts, or 'menu' when the panel hosts a menu.

The trigger's aria-haspopup is hinted to 'dialog' in tandem via the popover's haspopup signal; consumers overriding role here should also override haspopup on the trigger to match.

default 'dialog'
showArrowInput#boolean | undefined
input()

Show an arrow. Falls back to global config from providePopoverPanel(withArrow()).

default undefined, { alias: 'showArrow' }
showCloseInput#boolean | undefined
input()

Show a close button. Falls back to global config from providePopoverPanel(withCloseButton()).

default undefined, { alias: 'showClose' }

Bind an async state - drives loading, error, and empty slots from a single source. When set, takes precedence over individual [loading], [error], [empty] inputs.

variant#string | undefined
input()

Variant string - mapped to CSS class cngx-popover-panel--{variant}. Pre-themed: default, info, warning, danger, success. Add custom variants via CSS.

Instance Properties#

arrowTplDirective#unknown
contentChild()ProtectedReadonly
contentChild(CngxPopoverArrow)
bodyId#unknown
ProtectedReadonly
`${this.uid}-body`
closeTpl#unknown
contentChild()ProtectedReadonly
contentChild(CngxPopoverClose)
emptyTpl#unknown
contentChild()ProtectedReadonly
contentChild(CngxPopoverEmpty)
errorTpl#unknown
contentChild()ProtectedReadonly
contentChild(CngxPopoverError)
footerSlot#unknown
contentChild()ProtectedReadonly
contentChild(CngxPopoverFooter)
headerId#unknown
ProtectedReadonly
`${this.uid}-header`
headerSlot#unknown
contentChild()ProtectedReadonly
contentChild(CngxPopoverHeader)
loadingTpl#unknown
contentChild()ProtectedReadonly
contentChild(CngxPopoverLoading)

HostBindings#

BindingExpression
[class]hostClass()
[attr.role]role()
[attr.aria-labelledby]headerId
[attr.aria-describedby]ariaDescribedBy()
[attr.aria-busy]effectiveLoading() || null

Default visuals for CngxPopoverPanel. The host carries .cngx-popover-panel via hostClass(); the CngxPopover host directive toggles open / closing transition classes. The four semantic accents sit outside the foundation primary so an Ember- toned theme cannot accidentally tint a "success" panel.

State modifiers

Applied by CngxPopover to drive the open / close transition:

  • .cngx-popover--opening - opacity 0 + translate 4px / scale 0.98
  • .cngx-popover--open - resting state
  • .cngx-popover--closing - same as opening, animated outward
  • :popover-open - native popover restore-display

Accent variants

Each pins --cngx-popover-panel-accent + -accent-text on the panel and adds a border-left stripe. Child slots pick up both tokens via inheritance:

  • --info - blue accent
  • --success - success-coded
  • --warning - warning-coded
  • --danger - danger-coded

Arrow placement

Selected via [data-arrow-placement="top|bottom|left|right"] written by CngxPopover from live trigger / panel geometry. The 45-degree arrow square positions itself off the matching edge; --cngx-popover-arrow-offset (also written by CngxPopover) carries the live perpendicular offset, with a 50% fallback for the first paint before the offset computation lands.

Slots

  • __header - optional title row
  • __body - main content
  • __footer - action row, divided by top border
  • __header-row - header + optional close button
  • __close - circular dismiss button, hover wash + focus ring
  • __arrow - 45-degree square positioned by arrow-placement
  • __loading / __error / __empty - async-state surfaces; __error picks up --cngx-color-danger, __empty dims to 0.6

Inheritance

  • --cngx-popover-panel-bg -> --cngx-color-surface (via :root delegation so dark-mode surface cascades through automatically)
  • --cngx-popover-panel-color -> --cngx-color-text
  • Layout / motion / header / footer tokens - leaf, no fallback chain
  • Accent surface tokens - leaf; each variant rule pins them with light-mode defaults, the dark cascade overrides them at higher specificity outside the @scope wrap

Dark mode

Three hooks lift the alpha-on-black borders / shadow to alpha-on- white so they remain visible on dark surfaces, swap the close-button hover wash to white-alpha, and pin every variant accent to its dark-mode pair (lower L surface + lifted-L text):

  • prefers-color-scheme: dark
  • [data-color-scheme="dark"] / .dark class
  • [data-color-scheme="light"] / .light class (explicit pin)

Reduced motion

Under prefers-reduced-motion: reduce the opacity + transform transition is dropped so the panel snaps in and out.

Pair with

  • @cngx/themes/material/popover-panel-theme - Material 3 surface + elevation

Index#

Surface

--cngx-popover-panel-bg#<color>
Default value oklch(1 0 0)

Panel background. Falls back through --cngx-color-surface.

See: [[--cngx-color-surface]]

--cngx-popover-panel-color#<color>
Default value oklch(0.27 0.04 250)

Panel text color. Falls back through --cngx-color-text.

See: [[--cngx-color-text]]

--cngx-popover-panel-shadow#*
Default value 0 8px 24px oklch(0 0 0 / 0.12)

Drop-shadow shorthand for the panel. inherits: true so the :root dark-mode override reaches the open panel element.

--cngx-popover-panel-border#*
Default value 1px solid oklch(0 0 0 / 0.08)

Border shorthand for the panel.

Layout

--cngx-popover-panel-border-radius#<length>
Default value 12px

Corner radius of the panel.

--cngx-popover-panel-padding#<length>
Default value 16px

Padding shorthand applied inside the panel.

--cngx-popover-panel-max-width#<length>
Default value 360px

Maximum inline size - caps long content before the floater collides with viewport edges.

--cngx-popover-panel-arrow-size#<length>
Default value 8px

Side length of the arrow square (the rotated 45° diamond - final arrow side reads as size * sqrt(2)).

--cngx-popover-panel-close-size#<length>
Default value 28px

Diameter of the optional close button in the header row.

--cngx-popover-panel-header-gap#<length>
Default value 8px

Vertical gap between the header and the body slot.

Motion

--cngx-popover-panel-transition-duration#<time>
Default value 200ms

Duration of the opacity + transform transition between the open states.

--cngx-popover-panel-transition-easing#*
Default value cubic-bezier(0.4, 0, 0.2, 1)

Easing curve of the open / close transition.

Typography

--cngx-popover-panel-header-font-size#*
Default value 0.875rem

Font-size of the optional header slot.

--cngx-popover-panel-header-font-weight#<number>
Default value 600

Font-weight of the optional header slot.

Variant / Accent

--cngx-popover-panel-accent#*
Default value transparent

Accent surface for the semantic-variant rules (.cngx-popover-panel--info / --success / --warning / --danger). Each variant rule pins this token plus the matching accent-text token - child slots pick them up through currentColor and var() fallbacks.

--cngx-popover-panel-accent-text#*
Default value currentColor

Text / outline color paired with the accent surface - used by focus rings and the variant border-left rule.

State / Hover

--cngx-popover-panel-close-hover-bg#<color>
Default value oklch(0 0 0 / 0.06)

Hover wash on the optional close button. Light: 6% black wash; dark: 8% white wash. Both sit subtly on top of the panel surface without competing for attention.