Demos
How to import
import { Popconfirm } from '@fibrous/semi-ui-react';
Basic Usage
Popconfirm is based on the Tooltip component. Children support the same type as Tooltip. For details, please refer to Tooltip Cautions
Code
import { Popconfirm, Button, Toast } from '@fibrous/semi-ui-react';
export default function PopconfirmDemo() {
const onConfirm = () => {
Toast.success('确认保存!');
};
const onCancel = () => {
Toast.warning('取消保存!');
};
return (
<Popconfirm title="确定是否要保存此修改?" content="此修改将不可逆" onConfirm={onConfirm} onCancel={onCancel}>
<Button>保存</Button>
</Popconfirm>
);
}Type collocation
Developers can use scenario-based OK Type/Cancel Type/icon Equal parameters are matched with different styles of bubble confirmation boxes.
Code
import { useState } from 'react';
import { IconAlertTriangle } from '@fibrous/semi-icons-react';
import { Popconfirm, Radio, RadioGroup, Button, type RadioChangeEvent } from '@fibrous/semi-ui-react';
export default function PopconfirmDemo() {
const typeMap = {
default: {
icon: <IconAlertTriangle size="extra-large" />,
},
warning: {
icon: <IconAlertTriangle style={{ color: 'var(--semi-color-warning)' }} size="extra-large" />,
},
danger: {
okType: 'danger' as const,
icon: <IconAlertTriangle style={{ color: 'var(--semi-color-danger)' }} size="extra-large" />,
},
tertiary: {
icon: <IconAlertTriangle style={{ color: 'var(--semi-color-tertiary)' }} size="extra-large" />,
},
};
type TypeKey = keyof typeof typeMap;
const keys = Object.keys(typeMap) as TypeKey[];
const [type, setType] = useState<TypeKey>('default');
const [visible, setVisible] = useState(true);
const changeType = (e: RadioChangeEvent) => {
const type = e && e.target && e.target.value;
if (type && keys.includes(type)) {
setType(type);
}
};
return (
<div>
<RadioGroup type="button" onChange={changeType} value={type} style={{ marginTop: 14, marginBottom: 14 }}>
{keys.map((key) => (
<Radio key={key} value={key}>
<span style={{ color: `var(--semi-color-${key === 'default' ? 'primary' : key})` }}>{key}</span>
</Radio>
))}
</RadioGroup>
<div>
<Popconfirm {...typeMap[type]} visible={visible} onVisibleChange={setVisible} trigger="custom" title="确定是否要保存此修改?" content="此修改将不可逆">
<Button onClick={() => setVisible(!visible)}>点击此处</Button>
</Popconfirm>
</div>
</div>
);
}Delay hide
onConfirm and onCancel can be closed after click through return Promise.
When onCancel and onConfirm are triggered, the corresponding Button will automatically switch to loading: true
promise solve will close the bubble confirmation box, the bubble will remain when promise reject, and button loading will automatically switch to false
Code
import { Popconfirm, Button } from '@fibrous/semi-ui-react';
export default function PopconfirmDemo() {
const onConfirm = () => {
return new Promise<void>((resolve) => {
setTimeout(() => {
console.log('resolve,close popconfirm');
resolve();
}, 2000);
});
};
const onCancel = () => {
return new Promise((_resolve, reject) => {
setTimeout(() => {
console.log('reject, popconfirm still exist');
reject();
}, 2000);
});
};
return (
<Popconfirm title="确定是否要保存此修改?" content="此修改将不可逆" onConfirm={onConfirm} onCancel={onCancel}>
<Button>保存</Button>
</Popconfirm>
);
}Initialize the Focus Position of Popup Layer
okButtonProps and cancelButtonProps support passing in the autoFocus parameter, which will automatically focus at this position when the panel is opened.
content supports function, and its parameter is an object, which binds initialFocusRef to the focusable DOM or component, and it will automatically focus at this position when the panel is opened.
Code
import { Button, Popconfirm, Space } from '@fibrous/semi-ui-react';
export default function PopconfirmDemo() {
return (
<Space>
<Popconfirm
title="确定是否要保存此修改?"
content="此修改将不可逆"
okButtonProps={{
autoFocus: true,
type: 'danger',
}}
>
<Button>确认聚焦</Button>
</Popconfirm>
<Popconfirm
title="确定是否要保存此修改?"
content="此修改将不可逆"
cancelButtonProps={{
autoFocus: true,
}}
>
<Button>取消聚焦</Button>
</Popconfirm>
<Popconfirm
title="确定是否要保存此修改?"
content={({ initialFocusRef }) => {
return <input ref={initialFocusRef} placeholder="focus here" />;
}}
>
<Button>内容聚焦</Button>
</Popconfirm>
</Space>
);
}Use with Tooltip or Popover
Please refer to Use with Tooltip/Popover
API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| afterClose | Called after the card has closed and its leave animation has finished. | Type() => void | - |
| afterOpen | Called after the card has opened and its enter animation has finished, or right after opening when there is no enter animation, controlled or not. An open that is closed before the enter animation ends does not call it. | TooltipProps['afterOpen'] | - |
| aria-label | aria-label of the dialog. When given, it takes precedence over the title. | string | - |
| aria-labelledby | aria-labelledby of the dialog. Defaults to the title, or to the content without a title. | string | - |
| arrowPointAtCenter | Whether the arrow points at the center of the trigger. Requires showArrow. Defaults to true. | boolean | - |
| arrowStyle | Border color, background color and border opacity of the arrow. | ArrowStyle | - |
| autoAdjustOverflow | Whether the popup flips automatically when it would be clipped. Defaults to true. | boolean | - |
| cancelButtonProps | Props of the cancel button. autoFocus focuses it on open; className, style and other props land on the button. | ButtonProps | - |
| cancelText | Cancel button text. Defaults to the locale entry Popconfirm.cancel (取消 in zh_CN, Cancel in en_US). | string | - |
| cancelType | Cancel button type. | ButtonType | "tertiary" |
| children | The trigger. An element receives the trigger events and ARIA attributes. Other content such as text is wrapped in the span of Tooltip. | React.ReactNode | - |
| className | Class name of the confirmation card (.semi-popconfirm), not of the popup. | string | - |
| clickToHide | Whether a click on the popup or anything inside it closes it. | TooltipProps['clickToHide'] | - |
| closeOnEsc | Whether Esc closes the open card, wherever focus is; the topmost popup layer takes the key. Defaults to true. With trigger custom it only calls onEscKeyDown; with a controlled visible it also requests the close through onVisibleChange(false), and the caller decides whether to close. | TooltipProps['closeOnEsc'] | - |
| condition | Whether it may be triggered. Defaults to true. Only an explicit false disables the hover, click and focus triggers. Changing it from true to false closes an open card at once; with a controlled visible it only requests the close through onVisibleChange, and the card closes once the caller writes back. | boolean | - |
| content | Content of the card: a ReactNode or a function. The function receives { initialFocusRef }; pass initialFocusRef as the ref of the element that takes focus on open. | TooltipProps['content'] | - |
| contentClassName | Class name of the content container (.semi-popover) inside the popup. It is set apart from the className of the confirmation card. | string | any[] | - |
| defaultVisible | Whether it is initially shown when uncontrolled. | boolean | - |
| disableArrowKeyDown | Whether the arrow keys on the trigger are prevented from moving focus into the card. Defaults to false. | TooltipProps['disableArrowKeyDown'] | - |
| disabled | Whether it is disabled. A disabled Popconfirm renders only the trigger and never opens. | boolean | false |
| disableFocusListener | Whether keyboard focus is ignored when trigger is hover. Defaults to false. | boolean | - |
| guardFocus | Whether Tab cycles inside the card while focus is in it. Defaults to true. | TooltipProps['guardFocus'] | - |
| icon | Custom icon, a ReactNode. null or false renders no icon. | React.ReactNode | Type<IconAlertTriangle size="extra-large" /> |
| keepDOM | Whether the content stays mounted while closed. Defaults to false. | boolean | - |
| motion | Whether the popup animates when it appears and hides. Defaults to true. | boolean | - |
| mouseEnterDelay | Milliseconds before it shows after the pointer enters. Defaults to 50. Applies when trigger is hover or focus. | number | - |
| mouseLeaveDelay | Milliseconds before it hides after the pointer leaves. Defaults to 50. Applies when trigger is hover or focus. | number | - |
| okButtonProps | Props of the confirm button. autoFocus focuses it on open; className, style and other props land on the button. | ButtonProps | - |
| okText | Confirm button text. Defaults to the locale entry Popconfirm.confirm (确定 in zh_CN, Confirm in en_US). | string | - |
| okType | Confirm button type. | ButtonType | "primary" |
| onCancel | Called with the native MouseEvent when the cancel or close button is clicked. A returned Promise keeps the button loading and closes the card once it settles; a rejection keeps the card open. Any other return value is ignored. | Type(e: MouseEvent) => Promise<any> | void | - |
| onClickOutSide | Called with the native MouseEvent when the popup is shown and the mouse is pressed outside the trigger and the popup. | TooltipProps['onClickOutSide'] | - |
| onConfirm | Called with the native MouseEvent when the confirm button is clicked. A returned Promise keeps the button loading and closes the card once it settles; a rejection keeps the card open. Any other return value is ignored. | Type(e: MouseEvent) => Promise<any> | void | - |
| onEscKeyDown | Called with the native KeyboardEvent when Esc is pressed while the popup is open. | TooltipProps['onEscKeyDown'] | - |
| onOpen | Called once per opening when the card is shown, as its enter animation starts, before afterOpen, controlled or not. A hover open withdrawn because the pointer already left does not call it. | TooltipProps['onOpen'] | - |
| onVisibleChange | Called with the requested visibility. With a controlled visible it reports only requests from user interaction, not changes the caller makes to visible. | Type(visible: boolean) => void | - |
| position | Popup position: top, topLeft, topRight, left, leftTop, leftBottom, right, rightTop, rightBottom, bottom, bottomLeft or bottomRight. Defaults to bottomLeft (bottomRight in RTL). | Position | - |
| prefixCls | Class prefix of the confirmation card. | string | "semi-popconfirm" |
| ref | Reference that receives the handle, which only has the focusTrigger method. | TypeReact.Ref<PopconfirmHandle> | - |
| returnFocusOnClose | Whether focus returns to the trigger after closing. Defaults to true. It has no effect when trigger is custom, and works as usual with a controlled visible. | TooltipProps['returnFocusOnClose'] | - |
| role | ARIA role of the popup, whatever the trigger. | string | "dialog" |
| showArrow | Whether the arrow triangle is shown. Defaults to false. | boolean | - |
| showCloseIcon | Whether the close button in the top-right corner is shown. It calls onCancel. | boolean | true |
| spacing | Distance in pixels between the popup and the trigger. Defaults to 4, or 10 with showArrow. An object sets the horizontal and vertical distances. | number | { x: number; y: number } | - |
| stopPropagation | Whether click events on the popup stop bubbling. Clicks inside the card never reach document listeners. | boolean | string | true |
| style | Inline style of the confirmation card. | CSSProperties | - |
| title | Title, a string or a ReactNode. With a title, the dialog is named by it (see aria-labelledby). | React.ReactNode | - |
| trigger | When it shows: hover, focus, click, contextMenu or custom. With a controlled visible, trigger events only request opening or closing through onVisibleChange. | Trigger | "click" |
| visible | Controlled visibility. When given, this value decides whether it shows. Clicking the trigger, confirming, cancelling, clicking outside and Esc only request a change through onVisibleChange, which takes effect once the caller writes visible back. | boolean | - |
Methods
| Method | Description | Type |
|---|---|---|
| focusTrigger | Moves focus to the trigger element. It only takes effect when returnFocusOnClose is true and trigger is not custom. When disabled, there is no trigger element to focus and the call does nothing. | Type() => void |
className and style land on the confirmation card, and the className, style and other props in okButtonProps and cancelButtonProps land on their buttons (except autoFocus). aria-label and aria-labelledby land on the role="dialog" popup element, and with both a title and content it also carries aria-describedby pointing at the content. Other undeclared attributes are discarded.
Accessibility
ARIA
- Whatever the trigger,
hoverandfocusincluded, the Popconfirm popup has roledialog, named bytitle(bycontentwhen there is notitle); theroleprop overrides it - For the rest, please refer to Popover
Keyboard and focus
- Popconfirm must have trigger, trigger can be focused, use
Enterkey to open Popconfirm - After Popconfirm is activated, press the arrow key ⬇️ to move the focus to Popconfirm. The initial focus of Popconfirm should follow several principles:
- If the Popconfirm contains the last step of an irreversible process, such as: deleting data, etc., then this initial focus is preferably on the least destructive interactable element, such as: the cancel button (by passing the
autoFocusto the objectcancelButtonProps) - If you only read text in Popconfirm, it is recommended to set the initial focus on the most likely interactive elements, such as: confirm button (implemented by passing
autoFocusto the objectokButtonProps)
- If the Popconfirm contains the last step of an irreversible process, such as: deleting data, etc., then this initial focus is preferably on the least destructive interactable element, such as: the cancel button (by passing the
- Keyboard users can dismiss Popconfirm by pressing
Escand focus should return to the trigger. After the user closes the Pop through the interactive element within the Popconfirm, the focus should also return to the trigger (except when trigger iscustom) - When it is opened, after the user clicks
Escin the blank space in Popconfirm, the focus will also return to the trigger (except when trigger iscustom)
Design Tokens
| Sass variable | Value | Usage |
|---|---|---|
| $color-popconfirm_header-text | var(--semi-color-text-0) | 标题文字颜色 |
| $color-popconfirm_body-text | var(--semi-color-text-2) | 正文文字颜色 |
| $color-popconfirm_header_alert-icon | var(--semi-color-warning) | 警示图标颜色 |
| $width-popconfirm-icon | 24px | 图标宽度 |
| $width-popconfirm-maxWidth | 400px | 整体最大宽度 |
| $spacing-popconfirm-top | 24px | 顶部内边距 |
| $spacing-popconfirm-bottom | 20px | 底部内边距 |
| $spacing-popconfirm_with_arrow-padding | 12px | 顶部内边距 |
| $spacing-popconfirm_header_title-marginBottom | 8px | header 标题底部外边距 |
| $spacing-popconfirm_body_p-padding | 0 | body 正文内边距 |
| $spacing-popconfirm_body_p-margin | 0 | body 正文外边距 |
| $spacing-popconfirm_footer-marginTop | 25px | footer 顶部外边距 |
| $spacing-popconfirm_footer_btn-marginRight | 8px | footer 按钮右侧外边距 |
| $spacing-popconfirm_popover_with_arrow_inner-padding | ($spacing-popconfirm-top - $spacing-popconfirm_with_arrow-padding) ($spacing-popconfirm-top - $spacing-popconfirm_with_arrow-padding) ($spacing-popconfirm-top - $spacing-popconfirm_with_arrow-padding) ($spacing-popconfirm-bottom - $spacing-popconfirm_with_arrow-padding) | 带三角形箭头时的内边距 |
| $spacing-popconfirm_popover_with_arrow_inner_rtl-padding | ($spacing-popconfirm-top - $spacing-popconfirm_with_arrow-padding) ($spacing-popconfirm-bottom - $spacing-popconfirm_with_arrow-padding) ($spacing-popconfirm-top - $spacing-popconfirm_with_arrow-padding) ($spacing-popconfirm-top - $spacing-popconfirm_with_arrow-padding) | 带三角形箭头时的内边距(rtl) |
| $spacing-popconfirm_header_icon-marginRight | 12px | header 图标的右侧外边距 |
| $font-popconfirm_header_title-fontWeight | $font-weight-bold | header 标题字重 |
| $radius-popconfirm-popover | var(--semi-border-radius-medium) | 气泡确认框圆角大小 |
FAQ
-
Why does the Popconfirm floating layer lose its width and wrap unexpectedly when the width is not enough near the screen border?
After Chromium 104, the wrapping rendering strategy when the width of the screen border text is not enough has changed. For details, see issue #1022, the semi-side has been This problem was fixed in v2.17.0.