Skip to content

Commit cc3d78f

Browse files
committed
Prevent browser back navigation when ClearButton is focused (#580)
1 parent 502f0dd commit cc3d78f

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

src/__tests__/components/ClearButton.test.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import React from 'react';
33

44
import ClearButton from '../../components/ClearButton';
55

6+
import { BACKSPACE, RETURN } from '../../constants';
7+
68
describe('<ClearButton>', () => {
79
let button, onClick;
810

@@ -22,7 +24,32 @@ describe('<ClearButton>', () => {
2224
});
2325

2426
test('registers a click', () => {
25-
button.simulate('click', { stopPropagation: () => {} });
27+
const e = { stopPropagation: jest.fn() };
28+
button.simulate('click', e);
2629
expect(onClick).toHaveBeenCalledTimes(1);
30+
expect(e.stopPropagation).toHaveBeenCalledTimes(1);
31+
});
32+
33+
test('prevents the default backspace behavior', () => {
34+
const onKeyDown = jest.fn();
35+
button.setProps({ onKeyDown });
36+
37+
const backspace = {
38+
keyCode: BACKSPACE,
39+
preventDefault: jest.fn(),
40+
};
41+
button.simulate('keydown', backspace);
42+
43+
expect(onKeyDown).toHaveBeenCalledTimes(1);
44+
expect(backspace.preventDefault).toHaveBeenCalledTimes(1);
45+
46+
const enter = {
47+
keyCode: RETURN,
48+
preventDefault: jest.fn(),
49+
};
50+
button.simulate('keydown', enter);
51+
52+
expect(onKeyDown).toHaveBeenCalledTimes(2);
53+
expect(enter.preventDefault).toHaveBeenCalledTimes(0);
2754
});
2855
});

src/components/ClearButton.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,28 @@ import PropTypes from 'prop-types';
77
import { isSizeLarge, noop } from '../utils';
88

99
import { sizeType } from '../propTypes';
10-
import type { EventHandler, Size } from '../types';
10+
import type { EventHandler, KeyboardEventHandler, Size } from '../types';
11+
12+
import { BACKSPACE } from '../constants';
1113

1214
const propTypes = {
1315
label: PropTypes.string,
1416
onClick: PropTypes.func,
17+
onKeyDown: PropTypes.func,
1518
size: sizeType,
1619
};
1720

1821
const defaultProps = {
1922
label: 'Clear',
2023
onClick: noop,
24+
onKeyDown: noop,
2125
};
2226

2327
type Props = {
2428
className?: string,
2529
label: string,
2630
onClick: EventHandler<HTMLButtonElement>,
31+
onKeyDown: KeyboardEventHandler<HTMLButtonElement>,
2732
size?: Size,
2833
};
2934

@@ -36,19 +41,32 @@ const ClearButton = ({
3641
className,
3742
label,
3843
onClick,
44+
onKeyDown,
3945
size,
4046
...props
4147
}: Props) => (
4248
<button
4349
{...props}
4450
aria-label={label}
45-
className={cx('close', 'rbt-close', {
46-
'rbt-close-lg': isSizeLarge(size),
47-
}, className)}
51+
className={cx(
52+
'close',
53+
'rbt-close',
54+
{
55+
'rbt-close-lg': isSizeLarge(size),
56+
},
57+
className
58+
)}
4859
onClick={(e: SyntheticEvent<HTMLButtonElement>) => {
4960
e.stopPropagation();
5061
onClick(e);
5162
}}
63+
onKeyDown={(e: SyntheticKeyboardEvent<HTMLButtonElement>) => {
64+
// Prevent browser from navigating back.
65+
if (e.keyCode === BACKSPACE) {
66+
e.preventDefault();
67+
}
68+
onKeyDown(e);
69+
}}
5270
type="button">
5371
<span aria-hidden="true">&times;</span>
5472
<span className="sr-only">{label}</span>

0 commit comments

Comments
 (0)