diff --git a/src/expandable-section/__tests__/interactions.test.tsx b/src/expandable-section/__tests__/interactions.test.tsx index eeec3a7eba..62cfc4ad4e 100644 --- a/src/expandable-section/__tests__/interactions.test.tsx +++ b/src/expandable-section/__tests__/interactions.test.tsx @@ -188,4 +188,42 @@ describe('Expandable Section - Interactions', () => { expect(onButtonClickSpy).toHaveBeenCalledTimes(1); }); }); + + describe('Navigation variant header wrapper', () => { + let onChangeSpy: jest.Mock; + let onLinkClickSpy: jest.Mock; + + beforeEach(() => { + onChangeSpy = jest.fn(); + onLinkClickSpy = jest.fn(); + }); + + function renderNavigationSection(): ExpandableSectionWrapper { + return renderExpandableSection({ + onChange: onChangeSpy, + headerText: Header link, + variant: 'navigation', + }); + } + + test('toggles when the inert space around the expand button is clicked', () => { + const wrapper = renderNavigationSection(); + wrapper.findHeader().click(); + expect(onChangeSpy).toHaveBeenCalledTimes(1); + expect(onChangeSpy).toHaveBeenCalledWith(expect.objectContaining({ detail: { expanded: true } })); + }); + + test('toggles exactly once when the expand button is clicked', () => { + const wrapper = renderNavigationSection(); + wrapper.findExpandButton().click(); + expect(onChangeSpy).toHaveBeenCalledTimes(1); + }); + + test('does not toggle when a link in the header text is clicked', () => { + const wrapper = renderNavigationSection(); + wrapper.findHeader().findLink()!.click(); + expect(onChangeSpy).not.toHaveBeenCalled(); + expect(onLinkClickSpy).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/src/expandable-section/expandable-section-header.tsx b/src/expandable-section/expandable-section-header.tsx index c14266309c..b0c91cdb4d 100644 --- a/src/expandable-section/expandable-section-header.tsx +++ b/src/expandable-section/expandable-section-header.tsx @@ -187,6 +187,14 @@ const ExpandableNavigationHeader = ({ icon, expandIconPosition, }: ExpandableNavigationHeaderProps) => { + // Let clicks on the inert space around the expand button also toggle the section to provide + // a sufficiently large pointer target, deferring to interactive descendants like the expand button and links. + const onWrapperClick: MouseEventHandler = event => { + const interactiveElement = (event.target as HTMLElement).closest('a, button'); + if (!interactiveElement || !event.currentTarget.contains(interactiveElement)) { + onClick(event); + } + }; const expandButton = ( {expandIconPosition === 'end' ? ( <>