diff --git a/src/components/delete-button/delete-button.css b/src/components/delete-button/delete-button.css index 6abca7ec00c1ad04569236b4c3db73c53c02d1da..b8f937eff75853b49e364244d63cab3c03940182 100644 --- a/src/components/delete-button/delete-button.css +++ b/src/components/delete-button/delete-button.css @@ -6,11 +6,17 @@ display: flex; align-items: center; justify-content: center; + border-radius: 50%; user-select: none; cursor: pointer; transition: all 0.15s ease-out; } +.delete-button:focus { + outline: none; + box-shadow: 0px 0px 0px 4px $motion-transparent; +} + .delete-button-visible { display: flex; align-items: center; diff --git a/src/components/delete-button/delete-button.jsx b/src/components/delete-button/delete-button.jsx index 6e84fb983f3bffe4813e9fc9eb6a91105217ea3c..c4618d43fc9bf59d004ef21ab9f662ac0c19d995 100644 --- a/src/components/delete-button/delete-button.jsx +++ b/src/components/delete-button/delete-button.jsx @@ -1,39 +1,60 @@ import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; +import {defineMessages, injectIntl, intlShape} from 'react-intl'; import styles from './delete-button.css'; import deleteIcon from './icon--delete.svg'; -const DeleteButton = props => ( +const messages = defineMessages({ + delete: { + id: 'gui.deleteButton.delete', + description: 'Title of the button to delete a sprite, costume or sound', + defaultMessage: 'Delete' + } +}); + +const DeleteButtonComponent = ({ + className, + intl, + onClick, + setRef, + tabIndex, + ...props +}) => ( <div - aria-label="Delete" + aria-label={intl.formatMessage(messages.delete)} className={classNames( styles.deleteButton, - props.className + className )} + ref={setRef} role="button" - tabIndex={props.tabIndex} - onClick={props.onClick} + tabIndex={tabIndex} + onClick={onClick} + {...props} > <div className={styles.deleteButtonVisible}> <img className={styles.deleteIcon} + draggable={false} src={deleteIcon} /> </div> </div> - ); -DeleteButton.propTypes = { + +DeleteButtonComponent.propTypes = { className: PropTypes.string, + intl: intlShape, onClick: PropTypes.func.isRequired, + setRef: PropTypes.func.isRequired, tabIndex: PropTypes.number }; -DeleteButton.defaultProps = { +DeleteButtonComponent.defaultProps = { tabIndex: 0 }; -export default DeleteButton; +export default injectIntl(DeleteButtonComponent); diff --git a/src/components/sprite-selector-item/sprite-selector-item.jsx b/src/components/sprite-selector-item/sprite-selector-item.jsx index 458df186f94b4e4221d678511a99204ec16bad3d..e3ed71735cf0cb341eae0539fc30515731f4ac8b 100644 --- a/src/components/sprite-selector-item/sprite-selector-item.jsx +++ b/src/components/sprite-selector-item/sprite-selector-item.jsx @@ -2,7 +2,7 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import DeleteButton from '../delete-button/delete-button.jsx'; +import DeleteButton from '../../containers/delete-button.jsx'; import styles from './sprite-selector-item.css'; import {ContextMenuTrigger} from 'react-contextmenu'; import {DangerousMenuItem, ContextMenu, MenuItem} from '../context-menu/context-menu.jsx'; diff --git a/src/containers/delete-button.jsx b/src/containers/delete-button.jsx new file mode 100644 index 0000000000000000000000000000000000000000..600fbcdee52453ebc816d4e211f8e38604201139 --- /dev/null +++ b/src/containers/delete-button.jsx @@ -0,0 +1,52 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import bindAll from 'lodash.bindall'; + +import DeleteButtonComponent from '../components/delete-button/delete-button.jsx'; + +class DeleteButton extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleKeyPress', + 'setRef' + ]); + } + componentDidMount () { + document.addEventListener('keydown', this.handleKeyPress); + } + componentWillUnmount () { + document.removeEventListener('keydown', this.handleKeyPress); + } + setRef (ref) { + this.ref = ref; + } + handleKeyPress (event) { + if (this.ref === event.currentTarget.activeElement && (event.key === 'Enter' || event.key === ' ')) { + this.props.onClick(event); + event.preventDefault(); + } + } + render () { + return ( + <DeleteButtonComponent + className={this.props.className} + setRef={this.setRef} + tabIndex={this.props.tabIndex} + onClick={this.props.onClick} + /> + ); + } +} + +DeleteButton.propTypes = { + className: PropTypes.string, + onClick: PropTypes.func.isRequired, + tabIndex: PropTypes.number +}; + +DeleteButton.defaultProps = { + tabIndex: 0 +}; + +export default DeleteButton; diff --git a/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap b/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap index f7f19434a6109bf1772637da5b6e80ccc1a04143..36e1449333f0819bdf3f4fb123a75a706cb19b59 100644 --- a/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap +++ b/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap @@ -57,6 +57,7 @@ exports[`SpriteSelectorItemComponent matches snapshot when given a number and de > <img className={undefined} + draggable={false} src="test-file-stub" /> </div> @@ -141,6 +142,7 @@ exports[`SpriteSelectorItemComponent matches snapshot when selected 1`] = ` > <img className={undefined} + draggable={false} src="test-file-stub" /> </div> diff --git a/test/unit/components/sprite-selector-item.test.jsx b/test/unit/components/sprite-selector-item.test.jsx index fb103b4efc9e71211c0f99eac6e7f3339f1bd705..b274d967bb7c741d8a284cc7fb043a3aa2b91243 100644 --- a/test/unit/components/sprite-selector-item.test.jsx +++ b/test/unit/components/sprite-selector-item.test.jsx @@ -1,7 +1,7 @@ import React from 'react'; import {mountWithIntl, shallowWithIntl, componentWithIntl} from '../../helpers/intl-helpers.jsx'; import SpriteSelectorItemComponent from '../../../src/components/sprite-selector-item/sprite-selector-item'; -import DeleteButton from '../../../src/components/delete-button/delete-button'; +import DeleteButton from '../../../src/containers/delete-button.jsx'; describe('SpriteSelectorItemComponent', () => { let className;