Popover
Low-level primitive for custom contextual surfaces that do not fit a specialized Frakton NG component.
Import
import {FktPopoverComponent} from "frakton-ng/popover";Usage
Popover is a low-level primitive for custom contextual surfaces that do not fit a specialized Frakton NG component. Prefer Tooltip, Dialog, Select, Autocomplete, and other dedicated components when their interaction pattern matches the use case.
It renders content in the browser top layer without moving it to a global overlay container, so tokens, inherited classes, scoped styles, and animation classes keep flowing through the normal cascade. Popover owns disclosure and placement mechanics, but it does not assign menu, tooltip, dialog, or listbox semantics to arbitrary content.
Apply fktPopoverTrigger to the interactive control that owns the surface. Frakton synchronizes
aria-expanded and aria-controls; custom patterns remain responsible for the panel role and
name, aria-haspopup when applicable, internal keyboard behavior, and additional focus management.
Basic
The default trigger interaction opens on click, closes on outside click or Escape, and uses
bottom-center placement. The trigger remains the real interactive element and the content
template becomes the native popover panel. Apply fktPopoverTrigger to a keyboard-accessible
interactive element; the directive does not turn passive elements into controls.
Basic popover
Popover content rendered from a trigger-based template.
Hover and focus
Use triggerOn="hover" on the trigger for lightweight pointer and keyboard preview interactions.
Focus can move into the panel, and pointer movement between trigger and panel is protected by a
safe area. Prefer click for persistent, touch-first, or complex interactive flows.
Accessible hover
The same trigger opens on mouse hover and keyboard focus, then
closes when pointer and focus leave both trigger and panel.
Forms
Popover content is just Angular template content, so compact forms can live inside the panel without a special API.
@if (submitted(); as value) {
}
Positioning
Configure where the panel appears relative to the trigger and how it reacts when the requested placement does not fit.
Positions
Positions describe where the panel sits around the trigger. top and bottom are block sides;
start and end are inline sides. Corner positions use the *-corner suffix.
@for (group of groups; track group.label) {
{{ group.label }}
@for (position of group.positions; track position) {
{{ position.label }}
{{ position.description }}
}
}
Rtl positioning
Logical start and end positions follow the trigger direction by default. Use
positionDirection="ltr" or positionDirection="rtl" when geometry should be fixed
independently from the content direction.
Automatic content direction ({{ direction() === 'rtl' ? 'RTL' : 'LTR' }})
The positioning follows the selected direction. With positionDirection="auto",
end-center resolves from the trigger direction.
موضع تلقائي
The content and trigger share the selected direction, so logical end follows the same flow.
Fixed LTR positioning with {{ direction() === 'rtl' ? 'RTL' : 'LTR' }} content
The content follows the selected direction, but positionDirection="ltr"
keeps end-center resolved as LTR geometry.
محتوى RTL
Direction can be fixed for geometry without changing the content direction inside the panel.
Reposition
Use overflowStrategy="keep-position" when the preferred placement should be preserved, and call
repositionTo('fit') when content or layout changes after the popover is open. Programmatic
repositioning persists the resolved placement as the active preference.
Manual reposition
Overflow strategy is keeping the requested placement, so the preferred position is preserved
even if it overflows.
Trigger relative sizing
Use --fkt-popover-trigger-width with panel sizing tokens when the panel should derive its
width from the trigger. This keeps sizing in CSS instead of adding one-off width inputs.
@for (example of examples; track example.label) {
{{ example.label }}
{{ example.description }}
{{ example.token }}
}
Dismiss behavior
Automatic dismiss can be configured independently from state. dismiss reports the automatic
reason, while content actions close by updating the open state. Partial dismissOn objects
merge with the defaults, so omitted options keep their default behavior. Focus restoration is
explicit: Escape returns focus to the trigger, and content actions can call
restoreTriggerFocus() when returning keyboard users to the trigger is the desired flow.
Dismiss behavior
Outside click, Escape and scroll dismiss this popover.
Partial dismissOn values merge with the defaults.
Try to scroll, type ESC or click outside
State
Bind [(open)] when a parent component should observe or change the popover state directly.
Programmatic state
Bind [(open)] when the parent should observe or update the state. Use triggerOn="manual" when
the trigger's own handler or parent state should control activation. The directive still belongs on
the real interactive control and continues to provide aria-expanded, aria-controls, and the
positioning reference. This is not a separate controlled mode; trigger and dismiss behavior remain
configured independently.
Programmatic state
The parent owns the open signal. Manual mode leaves activation to the
trigger handler while Frakton keeps ARIA state and positioning
connected to that same control.
Customization
Customize the panel surface and motion with CSS tokens and native popover animation selectors.
Design tokens
The panel has a light default appearance and exposes styling hooks through CSS tokens instead of TypeScript style props.
Scoped tokens
The panel appearance comes from CSS variables.
Animations
Motion is class-based because the panel is a native popover. Use the built-in fade-slide,
disable it with none, or pass custom classes and animate with browser-native tools such as
:popover-open, @starting-style, allow-discrete, and transitions for display or overlay.
Keep animation classes local with fkt-popover ::ng-deep .my-animation-class, or put shared
animation classes in styles.css when they are reused across the app.
Uses the built-in fade-slide animation.
Uses a consumer-owned class for transition and starting style.
Uses a consumer-owned class for transition and starting style.
Disables the built-in animation class.