diff --git a/src/Panel.tsx b/src/Panel.tsx index 9373570..d7828e3 100644 --- a/src/Panel.tsx +++ b/src/Panel.tsx @@ -39,8 +39,14 @@ const CollapsePanel = React.forwardRef((prop onItemClick?.(panelKey); }, onKeyDown: (e: React.KeyboardEvent) => { + if (disabled || e.target !== e.currentTarget) { + return; + } if (e.key === 'Enter' || e.keyCode === KeyCode.ENTER || e.which === KeyCode.ENTER) { onItemClick?.(panelKey); + } else if (e.key === ' ') { + e.preventDefault(); + onItemClick?.(panelKey); } }, role: accordion ? 'tab' : 'button', diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index c91c7d9..a0f9013 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -445,6 +445,75 @@ describe('collapse', () => { ); }); + it('should toggle panel and prevent default when press space', () => { + const spaceKeyEvent = { + key: ' ', + keyCode: KeyCode.SPACE, + which: KeyCode.SPACE, + charCode: KeyCode.SPACE, + }; + + const { container } = render( + + + first + + + second + + + third + + , + ); + + const headers = container.querySelectorAll('.rc-collapse-header'); + expect(fireEvent.keyDown(headers[2], spaceKeyEvent)).toBe(true); + jest.runAllTimers(); + expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0); + + const header = headers[0]; + const defaultPrevented = !fireEvent.keyDown(header, spaceKeyEvent); + jest.runAllTimers(); + + expect(defaultPrevented).toBeTruthy(); + expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1); + expect(container.querySelector('.rc-collapse-panel')).toHaveClass('rc-collapse-panel-active'); + + fireEvent.keyDown(header, spaceKeyEvent); + jest.runAllTimers(); + + expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0); + }); + + it.each([{ key: 'Spacebar' }, { key: '', keyCode: KeyCode.SPACE }])( + 'should toggle for a normalized legacy space event: %o', + event => { + const { container } = render( + , + ); + expect(fireEvent.keyDown(container.querySelector('.rc-collapse-header')!, event)).toBe(false); + jest.runAllTimers(); + expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(1); + }, + ); + + it('should leave space on a nested extra button to the button', () => { + const { getByRole, container } = render( + Action, children: 'Content' }]} + />, + ); + + expect(fireEvent.keyDown(getByRole('button', { name: 'Action' }), { key: ' ' })).toBe(true); + jest.runAllTimers(); + expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0); + + expect(fireEvent.keyDown(getByRole('button', { name: 'Action' }), { key: 'Enter' })).toBe(true); + jest.runAllTimers(); + expect(container.querySelectorAll('.rc-collapse-panel-active')).toHaveLength(0); + }); + it('should link the header to its panel with aria-controls', () => { const { container } = render(