diff --git a/apps/web/src/__tests__/confirm-button.test.tsx b/apps/web/src/__tests__/confirm-button.test.tsx
index 3f23d44..32d03ba 100644
--- a/apps/web/src/__tests__/confirm-button.test.tsx
+++ b/apps/web/src/__tests__/confirm-button.test.tsx
@@ -195,4 +195,24 @@ describe("ConfirmButton", () => {
fireEvent.blur(button);
expect(screen.getByTestId("x-icon")).toBeTruthy();
});
+
+ it("Enter/Space keydown stops propagation to prevent parent handlers", () => {
+ const parentHandler = vi.fn();
+ render(
+ // biome-ignore lint/a11y/noStaticElementInteractions: test wrapper
+
+ }
+ label="Remove combatant"
+ onConfirm={vi.fn()}
+ />
+
,
+ );
+ const button = screen.getByRole("button");
+
+ fireEvent.keyDown(button, { key: "Enter" });
+ fireEvent.keyDown(button, { key: " " });
+
+ expect(parentHandler).not.toHaveBeenCalled();
+ });
});
diff --git a/apps/web/src/components/ui/confirm-button.tsx b/apps/web/src/components/ui/confirm-button.tsx
index 9763da6..0bb47b5 100644
--- a/apps/web/src/components/ui/confirm-button.tsx
+++ b/apps/web/src/components/ui/confirm-button.tsx
@@ -67,6 +67,12 @@ export function ConfirmButton({
};
}, [isConfirming, revert]);
+ const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
+ if (e.key === "Enter" || e.key === " ") {
+ e.stopPropagation();
+ }
+ }, []);
+
const handleClick = useCallback(
(e: React.MouseEvent) => {
e.stopPropagation();
@@ -95,6 +101,7 @@ export function ConfirmButton({
"bg-destructive text-primary-foreground rounded-md animate-confirm-pulse hover:bg-destructive hover:text-primary-foreground",
)}
onClick={handleClick}
+ onKeyDown={handleKeyDown}
onBlur={revert}
disabled={disabled}
aria-label={isConfirming ? `Confirm ${label.toLowerCase()}` : label}