Feedback · Popconfirm

Popconfirm

Used when the operation of the target element requires further confirmation from the user. Compared with Popover, it has a built-in series of configurable action buttons. Compared with Modal, it does not force full-screen centering, and the interaction is lighter.

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

PropertyDescriptionTypeDefault
afterCloseCalled after the card has closed and its leave animation has finished.Type() => void-
afterOpenCalled 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-labelaria-label of the dialog. When given, it takes precedence over the title.string-
aria-labelledbyaria-labelledby of the dialog. Defaults to the title, or to the content without a title.string-
arrowPointAtCenterWhether the arrow points at the center of the trigger. Requires showArrow. Defaults to true.boolean-
arrowStyleBorder color, background color and border opacity of the arrow.ArrowStyle-
autoAdjustOverflowWhether the popup flips automatically when it would be clipped. Defaults to true.boolean-
cancelButtonPropsProps of the cancel button. autoFocus focuses it on open; className, style and other props land on the button.ButtonProps-
cancelTextCancel button text. Defaults to the locale entry Popconfirm.cancel (取消 in zh_CN, Cancel in en_US).string-
cancelTypeCancel button type.ButtonType"tertiary"
childrenThe trigger. An element receives the trigger events and ARIA attributes. Other content such as text is wrapped in the span of Tooltip.React.ReactNode-
classNameClass name of the confirmation card (.semi-popconfirm), not of the popup.string-
clickToHideWhether a click on the popup or anything inside it closes it.TooltipProps['clickToHide']-
closeOnEscWhether 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']-
conditionWhether 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-
contentContent 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']-
contentClassNameClass name of the content container (.semi-popover) inside the popup. It is set apart from the className of the confirmation card.string | any[]-
defaultVisibleWhether it is initially shown when uncontrolled.boolean-
disableArrowKeyDownWhether the arrow keys on the trigger are prevented from moving focus into the card. Defaults to false.TooltipProps['disableArrowKeyDown']-
disabledWhether it is disabled. A disabled Popconfirm renders only the trigger and never opens.booleanfalse
disableFocusListenerWhether keyboard focus is ignored when trigger is hover. Defaults to false.boolean-
guardFocusWhether Tab cycles inside the card while focus is in it. Defaults to true.TooltipProps['guardFocus']-
iconCustom icon, a ReactNode. null or false renders no icon.React.ReactNodeType<IconAlertTriangle size="extra-large" />
keepDOMWhether the content stays mounted while closed. Defaults to false.boolean-
motionWhether the popup animates when it appears and hides. Defaults to true.boolean-
mouseEnterDelayMilliseconds before it shows after the pointer enters. Defaults to 50. Applies when trigger is hover or focus.number-
mouseLeaveDelayMilliseconds before it hides after the pointer leaves. Defaults to 50. Applies when trigger is hover or focus.number-
okButtonPropsProps of the confirm button. autoFocus focuses it on open; className, style and other props land on the button.ButtonProps-
okTextConfirm button text. Defaults to the locale entry Popconfirm.confirm (确定 in zh_CN, Confirm in en_US).string-
okTypeConfirm button type.ButtonType"primary"
onCancelCalled 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-
onClickOutSideCalled with the native MouseEvent when the popup is shown and the mouse is pressed outside the trigger and the popup.TooltipProps['onClickOutSide']-
onConfirmCalled 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-
onEscKeyDownCalled with the native KeyboardEvent when Esc is pressed while the popup is open.TooltipProps['onEscKeyDown']-
onOpenCalled 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']-
onVisibleChangeCalled 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-
positionPopup position: top, topLeft, topRight, left, leftTop, leftBottom, right, rightTop, rightBottom, bottom, bottomLeft or bottomRight. Defaults to bottomLeft (bottomRight in RTL).Position-
prefixClsClass prefix of the confirmation card.string"semi-popconfirm"
refReference that receives the handle, which only has the focusTrigger method.TypeReact.Ref<PopconfirmHandle>-
returnFocusOnCloseWhether 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']-
roleARIA role of the popup, whatever the trigger.string"dialog"
showArrowWhether the arrow triangle is shown. Defaults to false.boolean-
showCloseIconWhether the close button in the top-right corner is shown. It calls onCancel.booleantrue
spacingDistance 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 }-
stopPropagationWhether click events on the popup stop bubbling. Clicks inside the card never reach document listeners.boolean | stringtrue
styleInline style of the confirmation card.CSSProperties-
titleTitle, a string or a ReactNode. With a title, the dialog is named by it (see aria-labelledby).React.ReactNode-
triggerWhen it shows: hover, focus, click, contextMenu or custom. With a controlled visible, trigger events only request opening or closing through onVisibleChange.Trigger"click"
visibleControlled 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

MethodDescriptionType
focusTriggerMoves 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, hover and focus included, the Popconfirm popup has role dialog, named by title (by content when there is no title); the role prop overrides it
  • For the rest, please refer to Popover

Keyboard and focus

  • Popconfirm must have trigger, trigger can be focused, use Enter key 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 autoFocus to the object cancelButtonProps)
    • 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 autoFocus to the object okButtonProps )
  • Keyboard users can dismiss Popconfirm by pressing Esc and 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 is custom)
  • When it is opened, after the user clicks Esc in the blank space in Popconfirm, the focus will also return to the trigger (except when trigger is custom)

Design Tokens

These are the component's internal Sass variables and cannot be overridden. To customize styles, override the --semi-* CSS variables (see the Design Token page) or write unlayered CSS rules.
Sass variableValueUsage
$color-popconfirm_header-textvar(--semi-color-text-0)标题文字颜色
$color-popconfirm_body-textvar(--semi-color-text-2)正文文字颜色
$color-popconfirm_header_alert-iconvar(--semi-color-warning)警示图标颜色
$width-popconfirm-icon24px图标宽度
$width-popconfirm-maxWidth400px整体最大宽度
$spacing-popconfirm-top24px顶部内边距
$spacing-popconfirm-bottom20px底部内边距
$spacing-popconfirm_with_arrow-padding12px顶部内边距
$spacing-popconfirm_header_title-marginBottom8pxheader 标题底部外边距
$spacing-popconfirm_body_p-padding0body 正文内边距
$spacing-popconfirm_body_p-margin0body 正文外边距
$spacing-popconfirm_footer-marginTop25pxfooter 顶部外边距
$spacing-popconfirm_footer_btn-marginRight8pxfooter 按钮右侧外边距
$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-marginRight12pxheader 图标的右侧外边距
$font-popconfirm_header_title-fontWeight$font-weight-boldheader 标题字重
$radius-popconfirm-popovervar(--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.