diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index f33d32ed894974..2322d6f48ae73b 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -13,6 +13,7 @@
- `Popover`: Allow legitimate 0 positions to update popover position ([#51320](https://github.com/WordPress/gutenberg/pull/51320)).
- `Button`: Remove unnecessary margin from dashicon ([#51395](https://github.com/WordPress/gutenberg/pull/51395)).
- `Autocomplete`: Announce how many results are available to screen readers when suggestions list first renders ([#51018](https://github.com/WordPress/gutenberg/pull/51018)).
+- `ConfirmDialog`: Ensure onConfirm isn't called an extra time when submitting one of the buttons using the keyboard ([#51730](https://github.com/WordPress/gutenberg/pull/51730)).
### Internal
diff --git a/packages/components/src/confirm-dialog/component.tsx b/packages/components/src/confirm-dialog/component.tsx
index 92fb3fa08fbb17..b5c6cdf45f99af 100644
--- a/packages/components/src/confirm-dialog/component.tsx
+++ b/packages/components/src/confirm-dialog/component.tsx
@@ -7,7 +7,7 @@ import type { ForwardedRef, KeyboardEvent } from 'react';
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { useCallback, useEffect, useState } from '@wordpress/element';
+import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
/**
* Internal dependencies
@@ -42,6 +42,8 @@ function ConfirmDialog(
const cx = useCx();
const wrapperClassName = cx( styles.wrapper );
+ const cancelButtonRef = useRef();
+ const confirmButtonRef = useRef();
const [ isOpen, setIsOpen ] = useState< boolean >();
const [ shouldSelfClose, setShouldSelfClose ] = useState< boolean >();
@@ -69,7 +71,13 @@ function ConfirmDialog(
const handleEnter = useCallback(
( event: KeyboardEvent< HTMLDivElement > ) => {
- if ( event.key === 'Enter' ) {
+ // Avoid triggering the 'confirm' action when a button is focused,
+ // as this can cause a double submission.
+ const isConfirmOrCancelButton =
+ event.target === cancelButtonRef.current ||
+ event.target === confirmButtonRef.current;
+
+ if ( ! isConfirmOrCancelButton && event.key === 'Enter' ) {
handleEvent( onConfirm )( event );
}
},
@@ -96,12 +104,14 @@ function ConfirmDialog(
{ children }