Skip to content

Commit 3feff9f

Browse files
authored
Merge pull request scratchfoundation#5017 from chrisgarrity/fix-up-delete-button
Make delete button accessible
2 parents e23ac95 + 3701a4f commit 3feff9f

File tree

6 files changed

+92
-11
lines changed

6 files changed

+92
-11
lines changed

src/components/delete-button/delete-button.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66
display: flex;
77
align-items: center;
88
justify-content: center;
9+
border-radius: 50%;
910
user-select: none;
1011
cursor: pointer;
1112
transition: all 0.15s ease-out;
1213
}
1314

15+
.delete-button:focus {
16+
outline: none;
17+
box-shadow: 0px 0px 0px 4px $motion-transparent;
18+
}
19+
1420
.delete-button-visible {
1521
display: flex;
1622
align-items: center;
Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,60 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
33
import classNames from 'classnames';
4+
import {defineMessages, injectIntl, intlShape} from 'react-intl';
45

56
import styles from './delete-button.css';
67
import deleteIcon from './icon--delete.svg';
78

8-
const DeleteButton = props => (
9+
const messages = defineMessages({
10+
delete: {
11+
id: 'gui.deleteButton.delete',
12+
description: 'Title of the button to delete a sprite, costume or sound',
13+
defaultMessage: 'Delete'
14+
}
15+
});
16+
17+
const DeleteButtonComponent = ({
18+
className,
19+
intl,
20+
onClick,
21+
setRef,
22+
tabIndex,
23+
...props
24+
}) => (
925
<div
10-
aria-label="Delete"
26+
aria-label={intl.formatMessage(messages.delete)}
1127
className={classNames(
1228
styles.deleteButton,
13-
props.className
29+
className
1430
)}
31+
ref={setRef}
1532
role="button"
16-
tabIndex={props.tabIndex}
17-
onClick={props.onClick}
33+
tabIndex={tabIndex}
34+
onClick={onClick}
35+
{...props}
1836
>
1937
<div className={styles.deleteButtonVisible}>
2038
<img
2139
className={styles.deleteIcon}
40+
draggable={false}
2241
src={deleteIcon}
2342
/>
2443
</div>
2544
</div>
26-
2745
);
2846

29-
DeleteButton.propTypes = {
47+
48+
DeleteButtonComponent.propTypes = {
3049
className: PropTypes.string,
50+
intl: intlShape,
3151
onClick: PropTypes.func.isRequired,
52+
setRef: PropTypes.func.isRequired,
3253
tabIndex: PropTypes.number
3354
};
3455

35-
DeleteButton.defaultProps = {
56+
DeleteButtonComponent.defaultProps = {
3657
tabIndex: 0
3758
};
3859

39-
export default DeleteButton;
60+
export default injectIntl(DeleteButtonComponent);

src/components/sprite-selector-item/sprite-selector-item.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import classNames from 'classnames';
22
import PropTypes from 'prop-types';
33
import React from 'react';
44

5-
import DeleteButton from '../delete-button/delete-button.jsx';
5+
import DeleteButton from '../../containers/delete-button.jsx';
66
import styles from './sprite-selector-item.css';
77
import {ContextMenuTrigger} from 'react-contextmenu';
88
import {DangerousMenuItem, ContextMenu, MenuItem} from '../context-menu/context-menu.jsx';

src/containers/delete-button.jsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import PropTypes from 'prop-types';
2+
import React from 'react';
3+
import bindAll from 'lodash.bindall';
4+
5+
import DeleteButtonComponent from '../components/delete-button/delete-button.jsx';
6+
7+
class DeleteButton extends React.Component {
8+
constructor (props) {
9+
super(props);
10+
bindAll(this, [
11+
'handleKeyPress',
12+
'setRef'
13+
]);
14+
}
15+
componentDidMount () {
16+
document.addEventListener('keydown', this.handleKeyPress);
17+
}
18+
componentWillUnmount () {
19+
document.removeEventListener('keydown', this.handleKeyPress);
20+
}
21+
setRef (ref) {
22+
this.ref = ref;
23+
}
24+
handleKeyPress (event) {
25+
if (this.ref === event.currentTarget.activeElement && (event.key === 'Enter' || event.key === ' ')) {
26+
this.props.onClick(event);
27+
event.preventDefault();
28+
}
29+
}
30+
render () {
31+
return (
32+
<DeleteButtonComponent
33+
className={this.props.className}
34+
setRef={this.setRef}
35+
tabIndex={this.props.tabIndex}
36+
onClick={this.props.onClick}
37+
/>
38+
);
39+
}
40+
}
41+
42+
DeleteButton.propTypes = {
43+
className: PropTypes.string,
44+
onClick: PropTypes.func.isRequired,
45+
tabIndex: PropTypes.number
46+
};
47+
48+
DeleteButton.defaultProps = {
49+
tabIndex: 0
50+
};
51+
52+
export default DeleteButton;

test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ exports[`SpriteSelectorItemComponent matches snapshot when given a number and de
5757
>
5858
<img
5959
className={undefined}
60+
draggable={false}
6061
src="test-file-stub"
6162
/>
6263
</div>
@@ -141,6 +142,7 @@ exports[`SpriteSelectorItemComponent matches snapshot when selected 1`] = `
141142
>
142143
<img
143144
className={undefined}
145+
draggable={false}
144146
src="test-file-stub"
145147
/>
146148
</div>

test/unit/components/sprite-selector-item.test.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import {mountWithIntl, shallowWithIntl, componentWithIntl} from '../../helpers/intl-helpers.jsx';
33
import SpriteSelectorItemComponent from '../../../src/components/sprite-selector-item/sprite-selector-item';
4-
import DeleteButton from '../../../src/components/delete-button/delete-button';
4+
import DeleteButton from '../../../src/containers/delete-button.jsx';
55

66
describe('SpriteSelectorItemComponent', () => {
77
let className;

0 commit comments

Comments
 (0)