Overlay API
Complete API reference for @oge-ui/overlay. Note that OgeAnchoredPanel is a plain DI-free class (not a component) and resolvePopupPosition is a pure function — see the demos for the wiring pattern.
Properties Methods Events Types
OgeModal
oge-modalProperties 27
Content slots (structural directives)
| Name | Type | Default | Description |
|---|---|---|---|
*ogeModalTitle | OgeModalTitle | — | Rich title slot, replacing the plain title text. |
*ogeModalHeaderActions | OgeModalHeaderActions | — | Extra buttons rendered next to ✕. Presses that start here never begin a header drag. |
*ogeModalFooter | OgeModalFooter | — | Footer slot; $implicit is a close function whose optional argument becomes closed.result — <div *ogeModalFooter="let close">. |
| Name | Type | Default | Description |
|---|---|---|---|
opened | model<boolean> | false | Two-way open state. Setting it false directly closes without the guard pipeline. |
fullScreen | model<boolean> | false | Two-way full-screen state; size inputs are ignored while true. Driven by the maximize button when shown. |
title | string | undefined | — | Header text; also the aria-label fallback when the header is hidden. |
ariaLabel | string | undefined | — | Accessible name override for headerless modals. |
width / height / minWidth / minHeight / maxWidth / maxHeight | number | string | undefined | — | Panel size — numbers are px, strings pass through. Default width min(560px, 100%). |
placement | OgeModalPlacement | 'center' | Viewport position: centered or pinned near the top edge ('top', command-palette style). |
shading | boolean | true | Dims the page behind the modal. false keeps the backdrop transparent while staying fully modal. |
showCloseButton | boolean | true | Shows the header ✕ button. |
showMaximizeButton | boolean | false | Shows a maximize/restore toggle in the header, driving fullScreen. |
dragEnabled | boolean | false | Lets the user drag the panel by its header (viewport-clamped unless dragOutsideBoundary). |
dragOutsideBoundary | boolean | false | Allows dragging the panel beyond the viewport edges. |
restorePosition | boolean | true | Resets drag offset and resized size on every reopen. |
resizeEnabled | boolean | false | Shows a bottom-end resize handle (min 160×120, viewport-capped). |
inertBackground | boolean | false | Marks everything outside the modal inert while open — opt-in; content appended to body after opening is not covered. |
closeOnEscape | boolean | true | Escape closes the modal when it is the topmost overlay (popups inside close first). |
closeOnBackdropClick | boolean | true | A click that starts and ends on the backdrop closes the modal — a text-selection drag released outside never does. |
scrollLock | boolean | true | Locks body scroll while open (scrollbar-width compensated, ref-counted across stacked modals). |
autoFocus | OgeModalAutoFocus | 'first-tabbable' | Initial focus target; an [autofocus] element inside the panel always wins. |
restoreFocus | boolean | true | Restores focus to the opener on close — only when focus would otherwise be lost. |
padding | boolean | true | false makes the body flush for grids and custom layouts. |
busy | boolean | false | Spinner veil + aria-busy; user-initiated closes are blocked, programmatic close() still works. |
closeGuard | () => boolean | Promise<boolean> | undefined | — | Veto hook run before every pipeline close; may be async (single-flight — see closePending). A rejected promise vetoes with a dev warning. |
messages | Partial<OgeOverlayMessages> | undefined | — | Per-instance message overrides. |
closePending | Signal<boolean> | — | true while an async closeGuard is pending — disable footer actions with it. |
Methods 5
| Name | Type | Description |
|---|---|---|
open(): void | void | Opens the modal. |
close(result?: R): void | void | Closes through the full pipeline (closing → closeGuard); reason 'api', the argument becomes closed.result. |
toggle(): void | void | Open ⇄ close. |
focus(): void | void | Re-applies the initial-focus resolution. No-op while closed. |
toggleFullScreen(): void | void | Switches between windowed and full-screen (the maximize button’s action). |
Events 4
| Name | Type | Description |
|---|---|---|
opening | OgeModalOpeningEvent | Cancelable: fires before the modal opens (any open path). Set cancel = true to keep it closed. |
closing | OgeModalClosingEvent | Cancelable: fires before any pipeline close (Escape, backdrop, ✕, close()). Set cancel = true to keep the modal open. |
closed | OgeModalClosedEvent<R> | Fires after the modal closed, with the reason and the optional result. |
resizeStarted / resized | OgeModalResizeEvent | Fire when a resize gesture starts (starting size) and ends (final size). |
Types 9
| Name | Type | Description |
|---|---|---|
OgeModalCloseReason | 'api' | 'escape' | 'backdrop' | 'closeButton' | Why the modal closed. |
OgeModalClosingEvent | { reason: OgeModalCloseReason; cancel: boolean } | Cancelable pre-close event. |
OgeModalClosedEvent<R> | { reason: OgeModalCloseReason; result?: R } | Post-close event; result comes from close(result) or the slot close function. |
OgeModalAutoFocus | 'first-tabbable' | 'panel' | string | Initial-focus strategy — a plain string is treated as a CSS selector inside the panel. |
OgeModalPlacement | 'center' | 'top' | Where the panel sits in the viewport. |
OgeModalOpeningEvent | { cancel: boolean } | Cancelable pre-open event. |
OgeModalResizeEvent | { width: number; height: number; event: PointerEvent } | Payload of the resize outputs. |
OgeModalSlotContext | { $implicit: (result?: unknown) => void } | Context of *ogeModalTitle / *ogeModalHeaderActions / *ogeModalFooter; the function closes the modal. |
*ogeModalHeaderActions | structural slot | Custom title-bar buttons, rendered between the title and the maximize/✕ buttons; presses here never start a header drag. |
OgeModalService
Methods 1
| Name | Type | Description |
|---|---|---|
open<R, D>(content: Type<unknown> | TemplateRef, config?: OgeModalOpenConfig<D>): OgeModalRef<R> | OgeModalRef<R> | Opens a body-appended modal hosting the component or template — the escape hatch for transformed ancestors and for prompt/confirm flows without a declared <oge-modal>. |
Types 3
| Name | Type | Description |
|---|---|---|
OgeModalOpenConfig<D> | object | The declarative inputs minus slots (title, sizing, placement, closeGuard, …) plus data?: D, made available to the content via OGE_MODAL_DATA. |
OgeModalRef<R> | { close(result?: R): void; closed: Promise<OgeModalClosedEvent<R>> } | Handle of a service-opened modal; content components can inject it to close themselves with a result. |
OGE_MODAL_DATA | InjectionToken<unknown> | The config.data payload, injectable in the content component. |
OgeToastService
Properties 19
OgeToastOptions
| Name | Type | Default | Description |
|---|---|---|---|
message | string (required) | — | Body text; also the screen-reader announcement. |
title | string | undefined | — | Optional bold first line above the message. |
severity | OgeToastSeverity | 'info' | Drives the accent bar, icon and announcement mode. |
displayTime | number | config toastDisplayTime (4000) | Auto-dismiss time in ms. |
sticky | boolean | false | Never auto-dismisses (loading toasts are implicitly sticky). |
closable | boolean | true | Shows the ✕ button; aria label from messages.toastClose. |
closeOnClick | boolean | false | A click anywhere on the toast closes it (reason 'click'); button presses excluded. |
progressBar | boolean | config toastProgressBar (false) | Remaining-time bar — freezes exactly in sync with the paused timer. |
action | OgeToastAction | undefined | — | Inline action button; pressing it runs handler and closes with reason 'action'. |
position | OgeToastPosition | config toastPosition ('bottom-end') | Region override for this toast. |
announce | OgeToastAnnounce | severity-derived | 'assertive' for errors, 'polite' otherwise; 'off' silences. |
announceText | string | undefined | — | Screen-reader text override — announced instead of title + message, so the visual text can stay short. |
icon | TemplateRef<void> | undefined | — | Replaces the severity icon (the loading spinner still wins). |
loading | boolean | false | Spinner instead of the severity icon; implicitly sticky while true. |
coalesce | boolean | config toastCoalesceDuplicates (false) | Merge with an identical visible toast into one with a live ×N badge (timer restarts, same ref returned). |
id | string | undefined | — | Coalesce key override; defaults to severity+title+message. |
cssClass | string | undefined | — | Extra class(es) on the toast element. |
template | TemplateRef<OgeToastSlotContext> | undefined | — | Replaces the title/message body; $implicit closes the toast, data is in context. |
data | D | undefined | — | Arbitrary payload surfaced in the template context and action event. |
Methods 7
OgeToastService
| Name | Type | Description |
|---|---|---|
show<D>(toast: string | OgeToastOptions<D>): OgeToastRef<D> | OgeToastRef | Shows a toast; a bare string becomes an info toast. SSR-safe no-op. |
success / info / warning / error(message, options?): OgeToastRef | OgeToastRef | Severity sugar for show(). |
promise<T, D>(promise, options): OgeToastRef<D> | OgeToastRef | Sticky spinner toast that morphs in place when the promise settles; the timer starts then. success/error accept a message or a function returning a message or an update patch. |
clear(position?: OgeToastPosition): void | void | Closes every toast (or one region) with reason 'clear'. |
OgeToastRef
| Name | Type | Description |
|---|---|---|
close(): void | void | Closes the toast (reason 'api'). |
update(patch: OgeToastUpdate): void | void | Patches the toast in place; timing changes restart the timer, a changed message re-announces. |
closed | Promise<OgeToastClosedEvent> | Resolves after the toast closed (exit transition included), with the typed reason. |
Types 6
| Name | Type | Description |
|---|---|---|
OgeToastSeverity | 'info' | 'success' | 'warning' | 'error' | Toast severity. |
OgeToastPosition | 'top-start' | 'top-center' | 'top-end' | 'bottom-start' | 'bottom-center' | 'bottom-end' | Logical, RTL-aware region positions. |
OgeToastCloseReason | 'timeout' | 'closeButton' | 'click' | 'action' | 'api' | 'clear' | Why a toast closed. |
OgeToastAction<D> | { text: string; handler?: (event: OgeToastActionEvent<D>) => void } | Inline action button. |
OgeToastSlotContext<D> | { $implicit: () => void; data?: D } | Context of a template toast body. |
Config keys | toastPosition · toastDisplayTime · toastMaxVisible · toastProgressBar · toastCoalesceDuplicates | Defaults via provideOgeOverlayConfig(); strings via messages.toastClose/toastRegionLabel/toastCountBadge. |
OgeLiveAnnouncer
Methods 2
OgeLiveAnnouncer
| Name | Type | Description |
|---|---|---|
announce(message: string, options?: OgeLiveAnnounceOptions | OgeLivePoliteness): void | void | Speaks message through the polite (default) or assertive region. Written after delay ms (default 100) — a newer message to the same region inside that window supersedes it (debounce); the identical message inside a second is dropped; the region clears after clearAfter ms (default 5000) so a repeat is announced again. Empty text and the server are no-ops. |
clear(politeness?: OgeLivePoliteness): void | void | Empties one region (or both) and drops anything still pending. |
Types 4
| Name | Type | Description |
|---|---|---|
inject(OgeLiveAnnouncer) | Injectable({ providedIn: 'root' }) | Service in @oge-ui/overlay — the lowest Angular package the grid, tree list, Gantt, uploader and toast share. A no-op on the server platform. |
OgeLivePoliteness | 'polite' | 'assertive' | Which of the two shared regions speaks. |
OgeLiveAnnounceOptions | { politeness?: OgeLivePoliteness; delay?: number; clearAfter?: number } | delay: 0 writes synchronously — for a caller that already cleared and waited itself (the toast engine). |
OgeLiveAnnouncerCore / getOgeLiveAnnouncer(doc?) | @oge-ui/behavior | The framework-free engine both layers wrap: one polite and one assertive visually hidden aria-live region per document (.oge-live-announcer[data-oge-live-announcer], no role, created on the first announcement, never inerted by a modal’s inertBackground). Every OGE announcement — grid, tree list, toast, Gantt, uploader — goes through it; components never render their own live regions. |
OgeTooltip
[ogeTooltip]Properties 5
| Name | Type | Default | Description |
|---|---|---|---|
ogeTooltip | string (required) | — | Tooltip text. Applied to any element — the host gets aria-describedby pointing at the panel while it is shown. |
tooltipPlacement | OgePopupPlacement | 'top' | Preferred side; flips and clamps against the viewport like every anchored panel. |
tooltipShowDelay | number | undefined | — | Hover dwell before showing, in ms. Falls back to tooltipShowDelayMs from the overlay config. Keyboard focus always shows immediately. |
tooltipHideDelay | number | undefined | — | Grace period after the pointer leaves, in ms; falls back to tooltipHideDelayMs. |
tooltipDisabled | boolean | false | Suppresses the tooltip without removing the directive — hides an already open panel. |
OgeAnchoredPanel
Properties 15
Members
| Name | Type | Default | Description |
|---|---|---|---|
panelId | string | — | Unique id applied to the panel element (oge-popup-N) — wire to aria-controls. |
isOpen | Signal<boolean> | — | Open state. |
position | Signal<OgeResolvedPopupPosition | null> | — | null until the first measure after open; hide the panel while null. |
OgeAnchoredPanelOptions (constructor)
| Name | Type | Default | Description |
|---|---|---|---|
anchor | () => HTMLElement | null | — | Anchor element getter (null while not rendered). Required. |
panel | () => HTMLElement | null | — | Panel element getter (null while closed). Required. |
placement | () => OgePopupPlacement | 'bottom-start' | Reactive getter — read signals inside so the next update sees changes. |
width | () => number | 'anchor' | undefined | — | Fixed pixel value or 'anchor' to match the anchor width. |
offset | () => number | undefined | 4 | Main-axis gap between anchor and panel. |
viewportPadding | () => number | undefined | 8 | Minimum distance kept from viewport edges when clamping. |
closeOnOutsidePointerDown | boolean | true | Close on document pointerdown outside anchor+panel (capture phase, composedPath-aware). |
closeOnEscape | boolean | true | Close on Escape — stacked overlays only close the topmost. |
restoreFocus | () => void | — | Restores focus after closes caused by escape/select (only when focus would otherwise be orphaned). |
onClosed | (reason: OgePopupCloseReason) => void | — | Notified after every close with its reason. |
anchorRect | () => OgeRect | null | — | Virtual anchor rectangle used for positioning when it returns a rect — e.g. the pointer location of a context menu. |
transient | boolean | false | Transient surfaces (tooltips) skip the Escape stack so an open tooltip never swallows the Escape meant for the popup underneath. |
Methods 5
| Name | Type | Description |
|---|---|---|
open(): void | void | Opens (SSR-safe no-op without window); pushes onto the open-panel stack, adds listeners, measures. |
close(reason: OgePopupCloseReason = 'api'): void | void | Closes, removes listeners, restores focus for escape/select, then calls onClosed(reason). |
toggle(): void | void | Open ⇄ close. |
updatePosition(): void | void | Re-measures anchor/panel and recomputes the position (rAF-coalesced). Also runs automatically on scroll/resize/panel growth. |
destroy(): void | void | Removes every listener and pending frame; call from the owner's DestroyRef.onDestroy. |
Types 1
| Name | Type | Description |
|---|---|---|
OgePopupCloseReason | 'api' | 'outside' | 'escape' | 'select' | 'tab' | 'back' | Why a panel closed. |
OgePopup
oge-popupProperties 5
| Name | Type | Default | Description |
|---|---|---|---|
panel | OgeAnchoredPanel (required) | — | The anchored-panel model driving id, position and visibility. |
adaptive | 'popup' | 'sheet' | 'fullscreen' | 'popup' | Presentation: anchored, a modal full-width bottom sheet, or a full-screen dialog — role="dialog" + aria-modal, titled, with a close button; the shared OgeAdaptiveSheetCore (@oge-ui/behavior) locks scroll, inerts the background, traps Tab, moves focus in (an element marked data-oge-sheet-focus first), restores it, follows visualViewport above the on-screen keyboard and dismisses on a backdrop tap or a swipe down the handle. Popup editors resolve it from their adaptiveMode. |
adaptiveTitle | string | '' | Dialog title while adaptive (editors pass their field label). |
closeLabel | string | '' | Aria label of the adaptive close button, from the owner's messages catalog. |
[ogePopupSheetHeader] / [ogePopupSheetFooter] | content attribute | — | Projected under the adaptive title (a search field) and pinned at the bottom (a Done action); render them only while adaptive. |
Methods 2
Adaptive presentation helpers
| Name | Type | Description |
|---|---|---|
ogeAdaptivePresentation(mode, breakpoint, kind?): Signal<OgeAdaptivePresentation> | Signal<OgeAdaptivePresentation> | Injection-context helper every popup editor uses: 'popup' unless mode() is 'auto' and the viewport is narrower than breakpoint(), then kind ('sheet' default). Bind it to <oge-popup [adaptive]> in your own popup. |
ogeAdaptiveViewport(breakpoint): Signal<boolean> | Signal<boolean> | Whether the viewport is narrower than breakpoint() — follows matchMedia crossings, false during SSR. |
Types 1
| Name | Type | Description |
|---|---|---|
<oge-popup> | component | Presentational chrome: fixed positioning, popup surface tokens, --oge-z-popup stacking, transparent (via opacity, so the subtree stays focusable) until the first measure. Projects arbitrary content. |
resolvePopupPosition
Methods 1
| Name | Type | Description |
|---|---|---|
resolvePopupPosition(req: OgePopupPositionRequest): OgeResolvedPopupPosition | OgeResolvedPopupPosition | Pure anchored-popup placement: preferred side with flip when the opposite side has more room, cross-axis alignment fallback, and a final clamp into the viewport. Coordinates are viewport-relative (position: fixed). |
Types 14
OgePopupPositionRequest
| Name | Type | Default | Description |
|---|---|---|---|
anchor | OgeRect | — | Anchor rectangle (viewport-relative). Required. |
panel | { width: number; height: number } | — | Measured panel size. Required. |
viewport | { width: number; height: number } | — | Viewport size. Required. |
placement | OgePopupPlacement | — | Preferred placement. Required. |
offset | number | 4 | Gap between anchor and panel on the main axis. |
viewportPadding | number | 8 | Minimum distance kept from viewport edges when clamping. |
rtl | boolean | false | Resolves logical start/end (and left/right sides) against RTL. |
OgeResolvedPopupPosition
| Name | Type | Default | Description |
|---|---|---|---|
top / left | number | — | Viewport-relative — apply with position: fixed. |
placement | OgePopupPlacement | — | Logical placement actually used after flipping. |
width? | number | — | Panel width when anchor-width matching or a fixed width was requested (set by OgeAnchoredPanel, not by the pure function). |
Supporting types
| Name | Type | Default | Description |
|---|---|---|---|
OgePopupPlacement | 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end' | — | Side + cross-axis alignment. |
OgePopupSide | 'top' | 'bottom' | 'left' | 'right' | — | Main-axis side. |
OgePopupAlign | 'start' | 'end' | — | Cross-axis alignment. |
OgeRect | { top: number; left: number; width: number; height: number } | — | Structurally compatible with DOMRect. |
Overlay configuration
Methods 1
| Name | Type | Description |
|---|---|---|
provideOgeOverlayConfig(config: OgeOverlayConfigInput): Provider | Provider | Application- or component-scoped defaults. |
Types 8
OgeOverlayConfig
| Name | Type | Default | Description |
|---|---|---|---|
offset | number | 4 | Gap between anchor and panel on the main axis. |
viewportPadding | number | 8 | Minimum distance kept from viewport edges when clamping. |
typeAheadMs | number | 500 | Idle time after which the menu type-ahead buffer resets. |
menuShowDelayMs | number | 50 | Hover dwell time before a submenu parent row opens its submenu. |
menuHideDelayMs | number | 300 | Grace period before an open submenu closes after hovering a sibling row — the diagonal-pointer allowance. |
tooltipShowDelayMs / tooltipHideDelayMs | number | 400 / 100 | Hover dwell before a tooltip shows (focus shows immediately) and the grace period before it hides. |
toastPosition / toastDisplayTime / toastMaxVisible / toastProgressBar / toastCoalesceDuplicates | OgeToastPosition / number / number / boolean / boolean | 'bottom-end' / 4000 / 5 / false / false | Toast defaults. |
messages | OgeOverlayMessages | — | User-facing strings of the modal header buttons and the toast chrome: modalClose, modalMaximize, modalRestore, toastClose, toastRegionLabel, toastCountBadge. |
Overlay primitives
Methods 7
Escape stack
| Name | Type | Description |
|---|---|---|
pushOverlay(surface: object): void | void | Registers a surface as the new topmost overlay. No-op if it is already in the stack. |
removeOverlay(surface: object): void | void | Removes a surface from the stack; tolerates surfaces that were never pushed. |
isTopOverlay(surface: object): boolean | boolean | True only for the topmost surface. Gate your Escape handler on this and a popup opened inside a modal or a drawer closes before its host does. |
Focus trap
| Name | Type | Description |
|---|---|---|
getTabbableElements(root: HTMLElement): HTMLElement[] | HTMLElement[] | Tabbable descendants in DOM order. Recomputed per call rather than cached behind sentinel elements, so content added or removed after open is always accounted for. |
trapTabKey(event, root, fallback): void | void | Wraps Tab and Shift+Tab inside root. With no tabbable descendants it focuses fallback, so focus can never escape a modal surface. |
Scroll lock
| Name | Type | Description |
|---|---|---|
lockBodyScroll(): void | void | Locks body scroll and compensates for the scrollbar width. Ref-counted, so nested surfaces cannot unlock each other. |
unlockBodyScroll(): void | void | Releases one reference; the last release restores the inline styles exactly as they were. |
Notes
- The overlay config's
messagesblock is minimal — the anchored primitives render no user-facing strings (consumer components own their i18n); only the modal's and the toast's chrome labels live there. - Panels reposition (never detach) on capture-phase scroll and resize; a
ResizeObserveron the panel handles async content growth.