From a0a1e9f1c7d581195fdf49e92a26230cfb7a7198 Mon Sep 17 00:00:00 2001 From: jialecl Date: Fri, 7 Aug 2026 09:18:50 +0200 Subject: [PATCH 1/2] Added autoFocus events to manage focus on trigger --- .../popover/code/PopoverCodePage.tsx | 25 +++++++++++++-- packages/lib/src/popover/Popover.test.tsx | 31 ++++++++++++++++++- packages/lib/src/popover/Popover.tsx | 8 +++++ packages/lib/src/popover/types.ts | 6 ++++ 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/apps/website/screens/components/popover/code/PopoverCodePage.tsx b/apps/website/screens/components/popover/code/PopoverCodePage.tsx index 8dcd67c1e..e5004f080 100644 --- a/apps/website/screens/components/popover/code/PopoverCodePage.tsx +++ b/apps/website/screens/components/popover/code/PopoverCodePage.tsx @@ -95,10 +95,15 @@ const sections = [ {"() => void"} + Callback function when the popover is closed. + - + + + onCloseAutoFocus - Callback function when the popover is opened. Used only in controlled mode and if the trigger lacks the - events to manage the controlled behavior. + {"(event: Event) => void"} + Callback function when the popover is closed and the focus is set back to the trigger element. - @@ -106,7 +111,21 @@ const sections = [ {"() => void"} - Callback function when the popover is closed. + + Callback function when the popover is opened. Used only in controlled mode and if the trigger lacks the + events to manage the controlled behavior. + + - + + + onOpenAutoFocus + + {"(event: Event) => void"} + + + Callback function when the popover is opened and the focus is set to the first focusable element inside + the popover. + - diff --git a/packages/lib/src/popover/Popover.test.tsx b/packages/lib/src/popover/Popover.test.tsx index 5eb428b48..774e550af 100644 --- a/packages/lib/src/popover/Popover.test.tsx +++ b/packages/lib/src/popover/Popover.test.tsx @@ -1,4 +1,4 @@ -import { render } from "@testing-library/react"; +import { render, waitFor } from "@testing-library/react"; import DxcPopover from "./Popover"; import userEvent from "@testing-library/user-event"; import DxcButton from "../button/Button"; @@ -77,4 +77,33 @@ describe("Popover component tests", () => { userEvent.unhover(getByText("Trigger")); expect(onClose).toHaveBeenCalled(); }); + + test("The component manages onOpenAutoFocus", () => { + const autoFocusEvent = jest.fn(); + const { getByText, queryByText } = render( + Popover content}> + Trigger + + ); + expect(queryByText("Trigger")).toBeTruthy(); + userEvent.click(getByText("Trigger")); + expect(getByText("Popover content")).toBeTruthy(); + expect(autoFocusEvent).toHaveBeenCalled(); + }); + + test("The component manages onCloseAutoFocus", async () => { + const autoFocusEvent = jest.fn(); + const { getByText, queryByText } = render( + Popover content}> + Trigger + + ); + expect(queryByText("Trigger")).toBeTruthy(); + userEvent.click(getByText("Trigger")); + expect(getByText("Popover content")).toBeTruthy(); + userEvent.keyboard("{Escape}"); + await waitFor(() => { + expect(autoFocusEvent).toHaveBeenCalled(); + }); + }); }); diff --git a/packages/lib/src/popover/Popover.tsx b/packages/lib/src/popover/Popover.tsx index 05ae64753..6ea605579 100644 --- a/packages/lib/src/popover/Popover.tsx +++ b/packages/lib/src/popover/Popover.tsx @@ -39,7 +39,9 @@ const DxcPopover = ({ isOpen, offset = 4, onOpen, + onOpenAutoFocus, onClose, + onCloseAutoFocus, popoverContent, side = "bottom", }: PopoverPropsType): JSX.Element => { @@ -88,6 +90,12 @@ const DxcPopover = ({ align={align} side={side} sideOffset={offset} + onOpenAutoFocus={(event) => { + onOpenAutoFocus?.(event); + }} + onCloseAutoFocus={(event) => { + onCloseAutoFocus?.(event); + }} onInteractOutside={() => handleTrigger(isControlled.current, setOpened, false, onClose)} onEscapeKeyDown={() => handleTrigger(isControlled.current, setOpened, false, onClose)} onMouseEnter={ diff --git a/packages/lib/src/popover/types.ts b/packages/lib/src/popover/types.ts index 71a10d2c9..999ae1ed8 100644 --- a/packages/lib/src/popover/types.ts +++ b/packages/lib/src/popover/types.ts @@ -16,8 +16,14 @@ export type PopoverPropsType = { /** Callback function when the popover is opened. * Used only in controlled mode and if the trigger lacks the events to manage the controlled behavior. */ onOpen?: () => void; + /** Callback function when the popover is opened and the focus is set to the first focusable element inside the popover. + * */ + onOpenAutoFocus?: (event: Event) => void; /** Callback function when the popover is closed. */ onClose?: () => void; + /** Callback function when the popover is closed and the focus is set back to the trigger element. + * */ + onCloseAutoFocus?: (event: Event) => void; /** Content to be displayed inside the popover. */ popoverContent: React.ReactNode; /** Side of the trigger where the popover will appear. */ From 656edfb1ee0f2c4c17f64e2c2f1c95f3dee5fd19 Mon Sep 17 00:00:00 2001 From: jialecl Date: Fri, 7 Aug 2026 09:42:15 +0200 Subject: [PATCH 2/2] New tag added to the doc --- .../components/popover/code/PopoverCodePage.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/website/screens/components/popover/code/PopoverCodePage.tsx b/apps/website/screens/components/popover/code/PopoverCodePage.tsx index e5004f080..78d1d2529 100644 --- a/apps/website/screens/components/popover/code/PopoverCodePage.tsx +++ b/apps/website/screens/components/popover/code/PopoverCodePage.tsx @@ -99,7 +99,12 @@ const sections = [ - - onCloseAutoFocus + + + + onCloseAutoFocus + + {"(event: Event) => void"} @@ -118,7 +123,12 @@ const sections = [ - - onOpenAutoFocus + + + + onOpenAutoFocus + + {"(event: Event) => void"}