Skip to content

Commit 2713be4

Browse files
authored
[ButtonBase] Fix space calling onClick on keyDown instead of keyUp (#18319)
1 parent 8306c25 commit 2713be4

File tree

4 files changed

+44
-38
lines changed

4 files changed

+44
-38
lines changed

packages/material-ui/src/ButtonBase/ButtonBase.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ const ButtonBase = React.forwardRef(function ButtonBase(props, ref) {
182182
}
183183
});
184184

185+
const isNonNativeButton = () => {
186+
const button = getButtonNode();
187+
return component && component !== 'button' && !(button.tagName === 'A' && button.href);
188+
};
189+
185190
/**
186191
* IE 11 shim for https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat
187192
*/
@@ -206,15 +211,8 @@ const ButtonBase = React.forwardRef(function ButtonBase(props, ref) {
206211
onKeyDown(event);
207212
}
208213

209-
const button = getButtonNode();
210214
// Keyboard accessibility for non interactive elements
211-
if (
212-
event.target === event.currentTarget &&
213-
component &&
214-
component !== 'button' &&
215-
(event.key === ' ' || event.key === 'Enter') &&
216-
!(button.tagName === 'A' && button.href)
217-
) {
215+
if (event.target === event.currentTarget && isNonNativeButton() && event.key === 'Enter') {
218216
event.preventDefault();
219217
if (onClick) {
220218
onClick(event);
@@ -232,6 +230,14 @@ const ButtonBase = React.forwardRef(function ButtonBase(props, ref) {
232230
if (onKeyUp) {
233231
onKeyUp(event);
234232
}
233+
234+
// Keyboard accessibility for non interactive elements
235+
if (event.target === event.currentTarget && isNonNativeButton() && event.key === ' ') {
236+
event.preventDefault();
237+
if (onClick) {
238+
onClick(event);
239+
}
240+
}
235241
});
236242

237243
let ComponentProp = component;

packages/material-ui/src/ButtonBase/ButtonBase.test.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ describe('<ButtonBase />', () => {
680680
});
681681

682682
describe('keyboard accessibility for non interactive elements', () => {
683-
it('calls onClick when a spacebar is pressed on the element', () => {
683+
it('does not call onClick when a spacebar is pressed on the element', () => {
684684
const onClickSpy = spy(event => event.defaultPrevented);
685685
const { getByRole } = render(
686686
<ButtonBase onClick={onClickSpy} component="div">
@@ -694,7 +694,24 @@ describe('<ButtonBase />', () => {
694694
key: ' ',
695695
});
696696

697-
expect(onClickSpy.calledOnce).to.equal(true);
697+
expect(onClickSpy.callCount).to.equal(0);
698+
});
699+
700+
it('does call onClick when a spacebar is released on the element', () => {
701+
const onClickSpy = spy(event => event.defaultPrevented);
702+
const { getByRole } = render(
703+
<ButtonBase onClick={onClickSpy} component="div">
704+
Hello
705+
</ButtonBase>,
706+
);
707+
const button = getByRole('button');
708+
button.focus();
709+
710+
fireEvent.keyUp(document.activeElement || document.body, {
711+
key: ' ',
712+
});
713+
714+
expect(onClickSpy.callCount).to.equal(1);
698715
// defaultPrevented?
699716
expect(onClickSpy.returnValues[0]).to.equal(true);
700717
});
@@ -735,20 +752,20 @@ describe('<ButtonBase />', () => {
735752
expect(onClickSpy.callCount).to.equal(0);
736753
});
737754

738-
it('does not call onClick if Space was pressed on a child', () => {
755+
it('does not call onClick if Space was released on a child', () => {
739756
const onClickSpy = spy(event => event.defaultPrevented);
740-
const onKeyDownSpy = spy();
757+
const onKeyUpSpy = spy();
741758
render(
742-
<ButtonBase onClick={onClickSpy} onKeyDown={onKeyDownSpy} component="div">
759+
<ButtonBase onClick={onClickSpy} onKeyUp={onKeyUpSpy} component="div">
743760
<input autoFocus type="text" />
744761
</ButtonBase>,
745762
);
746763

747-
fireEvent.keyDown(document.activeElement, {
764+
fireEvent.keyUp(document.activeElement, {
748765
key: ' ',
749766
});
750767

751-
expect(onKeyDownSpy.callCount).to.equal(1);
768+
expect(onKeyUpSpy.callCount).to.equal(1);
752769
expect(onClickSpy.callCount).to.equal(0);
753770
});
754771

packages/material-ui/src/Chip/Chip.js

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,6 @@ const Chip = React.forwardRef(function Chip(props, ref) {
277277
label,
278278
onClick,
279279
onDelete,
280-
onKeyDown,
281280
onKeyUp,
282281
size = 'medium',
283282
variant = 'default',
@@ -295,21 +294,6 @@ const Chip = React.forwardRef(function Chip(props, ref) {
295294
}
296295
};
297296

298-
const handleKeyDown = event => {
299-
if (onKeyDown) {
300-
onKeyDown(event);
301-
}
302-
303-
// Ignore events from children of `Chip`.
304-
if (event.currentTarget !== event.target) {
305-
return;
306-
}
307-
308-
if ([' ', 'Enter', 'Backspace', 'Delete', 'Escape'].indexOf(event.key) !== -1) {
309-
event.preventDefault();
310-
}
311-
};
312-
313297
const handleKeyUp = event => {
314298
if (onKeyUp) {
315299
onKeyUp(event);
@@ -409,7 +393,6 @@ const Chip = React.forwardRef(function Chip(props, ref) {
409393
aria-disabled={disabled ? true : undefined}
410394
tabIndex={clickable || onDelete ? 0 : undefined}
411395
onClick={onClick}
412-
onKeyDown={handleKeyDown}
413396
onKeyUp={handleKeyUp}
414397
ref={handleRef}
415398
{...moreProps}

packages/material-ui/src/Chip/Chip.test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,15 +416,15 @@ describe('<Chip />', () => {
416416
onClickSpy.resetHistory();
417417
});
418418

419-
it('should call onClick when `space` is pressed ', () => {
419+
it('should call onClick when `space` is released ', () => {
420420
const preventDefaultSpy = spy();
421421
const spaceKeyDown = {
422422
preventDefault: preventDefaultSpy,
423423
key: ' ',
424424
};
425425
wrapper.find('div').simulate('keyDown', spaceKeyDown);
426-
assert.strictEqual(preventDefaultSpy.callCount, 2);
427-
assert.strictEqual(onClickSpy.callCount, 1);
426+
assert.strictEqual(preventDefaultSpy.callCount, 0);
427+
assert.strictEqual(onClickSpy.callCount, 0);
428428

429429
const spaceKeyUp = {
430430
key: ' ',
@@ -441,7 +441,7 @@ describe('<Chip />', () => {
441441
key: 'Enter',
442442
};
443443
wrapper.find('div').simulate('keyDown', enterKeyDown);
444-
assert.strictEqual(preventDefaultSpy.callCount, 2);
444+
assert.strictEqual(preventDefaultSpy.callCount, 1);
445445
assert.strictEqual(onClickSpy.callCount, 1);
446446

447447
const enterKeyUp = {
@@ -464,7 +464,7 @@ describe('<Chip />', () => {
464464
key: 'Backspace',
465465
};
466466
wrapper.find('div').simulate('keyDown', backspaceKeyDown);
467-
assert.strictEqual(preventDefaultSpy.callCount, 1);
467+
assert.strictEqual(preventDefaultSpy.callCount, 0);
468468
assert.strictEqual(onDeleteSpy.callCount, 0);
469469

470470
const backspaceKeyUp = {
@@ -485,7 +485,7 @@ describe('<Chip />', () => {
485485
key: 'Delete',
486486
};
487487
wrapper.find('div').simulate('keyDown', backspaceKeyDown);
488-
assert.strictEqual(preventDefaultSpy.callCount, 1);
488+
assert.strictEqual(preventDefaultSpy.callCount, 0);
489489
assert.strictEqual(onDeleteSpy.callCount, 0);
490490

491491
const backspaceKeyUp = {

0 commit comments

Comments
 (0)