Popconfirm
popconfirmConfirms a nearby action in a compact anchored popup.
Usage
Basic usage
Wrap any trigger element and click the pop-up bubble to confirm. onConfirm triggers and automatically closes after point confirmation.
<Popconfirm title="Confirm submission?" onConfirm={() => {}}>
<Button size="sm">Submit</Button>
</Popconfirm>Dangerous operation
danger Make the confirmation button turn danger color and the default icon turn red, suitable for irreversible actions such as deletion.
<Popconfirm title="Are you sure you want to delete this record?" description="It cannot be recovered after deletion." danger onConfirm={() => {}}>
<Button variant="outline" tone="danger" size="sm">Delete</Button>
</Popconfirm>Asynchronous confirmation
onConfirm Confirm button enters loading when returning to Promise, and automatically closes after resolve.
<Popconfirm
title="Confirm archiving?"
description="Save asynchronously to server."
okText="Archive"
onConfirm={() => new Promise((r) => setTimeout(r, 1200))}
>
<Button variant="outline" size="sm">Archive</Button>
</Popconfirm>Pop-up direction + custom icon
side controls the floating layer orientation, and icon replaces the default warning triangle.
<Popconfirm
title="Move to trash?"
side="right"
icon={<Trash2 className="size-5 shrink-0 text-danger" aria-hidden />}
danger
onConfirm={() => {}}
>
<Button variant="ghost" size="sm" tone="danger">Recycling</Button>
</Popconfirm>Custom button copy
okText / cancelText Override the default text of the confirm and cancel buttons.
<Popconfirm title="Log out?" okText="Log out" cancelText="Think again" onConfirm={() => {}}>
<Button variant="outline" size="sm">Log out</Button>
</Popconfirm>When to use
Use Popconfirm beside a table row or button when a dangerous or irreversible action such as Delete or Archive needs lightweight confirmation. It is more substantial than Toast but lighter than a full-screen Modal or AlertDialog.
Import
import { Popconfirm } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| danger | boolean | false | Uses danger tone for the confirm button and default icon. |
| open | boolean | — | Controlled open state, paired with onOpenChange. |
| defaultOpen | boolean | false | Initial open state when uncontrolled. |
| side | "top"|"right"|"bottom"|"left" | "top" | Preferred popup side. |
| align | "start"|"center"|"end" | "center" | Popup alignment. |
| sideOffset | number | 8 | Distance from the trigger. |
| disabled | boolean | false | Keeps the trigger visible but prevents opening. |
| className | string | — | Class name forwarded to Popup. |
Events
| Event | Type | Description |
|---|---|---|
| onConfirm | () => void | Promise<void> | A Promise puts Confirm in loading state, closes on resolve, and stays open after reject. |
| onCancel | () => void | Called only by the explicit Cancel button, not outside click or Escape. |
| onOpenChange | (open: boolean) => void | Reports all open-state changes, including outside click, Escape, Confirm, and Cancel. |
Slots
| Slot | Type | Description |
|---|---|---|
| title* | ReactNode | Confirmation question connected with aria-labelledby. |
| description | ReactNode | Supporting copy connected with aria-describedby. |
| icon | ReactNode | undefined uses the warning triangle, null omits it, and a node replaces it. |
| okText | ReactNode | Confirm copy. Defaults to built-in Chinese "\u786e\u8ba4", meaning “Confirm.” |
| cancelText | ReactNode | Cancel copy. Defaults to built-in Chinese "\u53d6\u6d88", meaning “Cancel.” |
| children* | ReactElement | Single trigger element used as the positioning anchor. |
Example
<Popconfirm title="Delete this record?" description="Deletion cannot be undone." danger onConfirm={() => {}}>
<Button variant="outline" tone="danger" size="sm">Delete</Button>
</Popconfirm>
<Popconfirm title="Archive this record?" okText="Archive" onConfirm={async () => { await api.archive(id); }}>
<Button variant="outline" size="sm">Archive</Button>
</Popconfirm>Usage guidelines
- When
onConfirmreturns a Promise, only resolve closes. Rejection clears loading and remains open; the caller owns error feedback. onCancelruns only for the explicit button. Put cleanup that must run for outside click or Escape inonOpenChange.childrenmust be one ReactElement, not text or a Fragment, because it anchors the popup.- In controlled use, always pair
openandonOpenChangeor dismissal cannot update state.
Related
Alert · Banner · Toast · Notification · ServiceMessage · Result
Playground
<Popconfirm
title="Are you sure you want to delete this record?"
description="Cannot be recovered after deletion."
danger
side="top"
onConfirm={async () => { await api.remove(id); }}
>
<Button variant="outline" tone="danger" size="sm">Delete</Button>
</Popconfirm>