useConfirmDialog
Hook that manages confirmation dialog overlays with icon, message, and action button support.
Usage#
import { useMotion } from '@primereact/core/motion';
import { useConfirmDialog } from '@primereact/headless/confirmdialog';
import { usePortal } from '@primereact/headless/portal';
import * as React from 'react';
import { createPortal } from 'react-dom';const { rootProps, triggerProps, backdropProps, positionerProps, popupProps, closeProps, headerProps, contentProps } = useConfirmDialog();
const portal = usePortal();
<div {...rootProps}>
<button {...triggerProps}></button>
{portal.state.mounted &&
createPortal(
<>
<div {...backdropProps} />
<div {...positionerProps}>
<div {...popupProps}>
<div {...headerProps}>
<button {...closeProps}></button>
</div>
<div {...contentProps}>...</div>
</div>
</div>
</>,
document.bodyuseConfirmDialog extends useDialog with a confirmation-oriented API. See Primitive for a component-based API.
Features#
- Confirmation lifecycle — open/close state with backdrop dismissal, escape handling, and automatic focus on the primary action
- Focus management — traps focus between Accept and Reject controls and restores it to the trigger on dismiss
- Positioning — nine preset positions plus
data-positionfor CSS-based layout variations - Scroll and layering — body scroll lock paired with
baseZIndex/autoZIndexto stack above other overlays - Portal-ready — designed to pair with
usePortalandcreatePortalfor SSR-safe body portaling - Imperative controls —
close()method andstate.openflag for programmatic dismissal and conditional rendering
Working with callbacks#
Controlled open state#
Pass open and onOpenChange to drive visibility from external state — useful when the confirmation is triggered by business logic.
const [isOpen, setIsOpen] = React.useState(false);
const confirmdialog = useConfirmDialog({
open: isOpen,
onOpenChange: (e) => setIsOpen(e.value)
});Accept and reject actions#
Wire the confirm flow by closing the dialog from both buttons and performing side effects in the handler.
const confirmdialog = useConfirmDialog();
const handleAccept = async () => {
await deleteItem();
confirmdialog.close();
};
<button onClick={handleAccept}>Yes</button>
<button {...confirmdialog.closeProps}>No</button>Top-aligned layout#
Use the position prop when the confirmation should appear near the top of the viewport instead of centered.
const confirmdialog = useConfirmDialog({ position: 'top' });Stacking with other overlays#
Combine baseZIndex with autoZIndex so each confirmation renders above the dialog that spawned it.
const confirmdialog = useConfirmDialog({ baseZIndex: 1200, autoZIndex: true });Styling with data attributes#
The hook exposes state through data-* attributes on each part. Use them as CSS selectors — no className juggling.
| Scope | Part | States |
|---|---|---|
confirmdialog | root | data-open, data-closed |
confirmdialog | popup | data-open, data-closed |
confirmdialog | positioner | data-position, data-scroll-behavior |
[data-scope='confirmdialog'][data-part='positioner'] {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
}
[data-scope='confirmdialog'][data-part='positioner'][data-position='top'] {
align-items: flex-start;
}API#
useConfirmDialog#
| Name | Type | Default |
|---|---|---|
open | boolean | — |
| Specifies the visibility of the dialog. | ||
defaultOpen | boolean | — |
| Specifies the default visibility of the dialog. | ||
draggable | boolean | true |
| Enables dragging to change the position using header. | ||
keepInViewport | boolean | true |
| Keeps dialog in the viewport. | ||
trapped | boolean | true |
| When enabled, focus is trapped within the dialog (modal behavior). | ||
modal | boolean | true |
| Whether the dialog is modal. When true, the positioner blocks pointer events behind it. | ||
dismissable | boolean | false |
| Specifies if clicking the modal background should hide the dialog. | ||
closeOnEscape | boolean | true |
| Specifies if pressing escape key should hide the dialog. | ||
blockScroll | boolean | false |
| Whether background scroll should be blocked when dialog is visible. | ||
baseZIndex | number | 0 |
| Base zIndex value to use in layering. | ||
autoZIndex | boolean | true |
| Whether to automatically manage layering. | ||
appendTo | "body" | HTMLElement | "self" | body |
| A valid query selector or an HTMLElement to specify where the dialog gets attached. | ||
position | "center" | "top" | "bottom" | "left" | "right" | "topleft" | "topright" | "bottomleft" | "bottomright" | center |
| Position of the dialog. | ||
fullScreen | boolean | false |
| Whether the dialog should open in full screen (maximized) mode. | ||
scrollBehavior | "inside" | "outside" | 'inside' |
| Defines the scroll behavior of the dialog. When set to 'inside', the dialog content area scrolls. When set to 'outside', the positioner scrolls allowing the entire dialog to scroll within the viewport. | ||
onOpenChange | (event: useDialogChangeEvent) => void | — |
| Callback function that is called when the trigger is clicked. | ||
Accessibility#
Escape dismisses, Tab cycles between Accept and Reject buttons, and focus auto-moves into the dialog when it opens. See Primitive for full WAI-ARIA compliance details.