diff --git a/src/components/delete-button/delete-button.css b/src/components/delete-button/delete-button.css new file mode 100644 index 0000000000000000000000000000000000000000..3224e23b9dec61f3641b25fc539a690495f751c0 --- /dev/null +++ b/src/components/delete-button/delete-button.css @@ -0,0 +1,43 @@ +@import "../../css/colors.css"; +@import "../../css/units.css"; + +/* the delete button has .25rem invisible 'slop' around the visible button + to make it easier to tap on a touch device */ +.delete-button { + display: flex; + align-items: center; + justify-content: center; + + overflow: hidden; /* Mask the icon animation */ + width: 2rem; + height: 2rem; + user-select: none; + cursor: pointer; + transition: all 0.15s ease-out; + +} + +.delete-button-visible { + display: flex; + align-items: center; + justify-content: center; + + overflow: hidden; /* Mask the icon animation */ + width: 1.75rem; + height: 1.75rem; + box-shadow: 0px 0px 0px 2px $motion-transparent; + background-color: $motion-primary; + color: $ui-white; + border-radius: 50%; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + user-select: none; + cursor: pointer; + transition: all 0.15s ease-out; +} + +.delete-icon { + position: relative; + margin: 0.25rem; + user-select: none; + transform-origin: 50%; +} diff --git a/src/components/delete-button/delete-button.jsx b/src/components/delete-button/delete-button.jsx new file mode 100644 index 0000000000000000000000000000000000000000..6e84fb983f3bffe4813e9fc9eb6a91105217ea3c --- /dev/null +++ b/src/components/delete-button/delete-button.jsx @@ -0,0 +1,39 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; + +import styles from './delete-button.css'; +import deleteIcon from './icon--delete.svg'; + +const DeleteButton = props => ( + <div + aria-label="Delete" + className={classNames( + styles.deleteButton, + props.className + )} + role="button" + tabIndex={props.tabIndex} + onClick={props.onClick} + > + <div className={styles.deleteButtonVisible}> + <img + className={styles.deleteIcon} + src={deleteIcon} + /> + </div> + </div> + +); + +DeleteButton.propTypes = { + className: PropTypes.string, + onClick: PropTypes.func.isRequired, + tabIndex: PropTypes.number +}; + +DeleteButton.defaultProps = { + tabIndex: 0 +}; + +export default DeleteButton; diff --git a/src/components/delete-button/icon--delete.svg b/src/components/delete-button/icon--delete.svg new file mode 100644 index 0000000000000000000000000000000000000000..3edd347dd6a7af3e0121fa09578ec3deed95f8cc Binary files /dev/null and b/src/components/delete-button/icon--delete.svg differ diff --git a/src/components/sprite-selector-item/sprite-selector-item.css b/src/components/sprite-selector-item/sprite-selector-item.css index 6844ef1c52c2e5c328b4eb668adddb12dd14d50e..dffc189023154b00c2fad62aca907831eea56d15 100644 --- a/src/components/sprite-selector-item/sprite-selector-item.css +++ b/src/components/sprite-selector-item/sprite-selector-item.css @@ -94,16 +94,16 @@ .delete-button { position: absolute; - top: 0.125rem; + top: -.625rem; z-index: auto; } [dir="ltr"] .delete-button { - right: 0.125rem; + right: -.625rem; } [dir="rtl"] .delete-button { - left: 0.125rem; + left: -.625rem; } .number { diff --git a/src/components/sprite-selector-item/sprite-selector-item.jsx b/src/components/sprite-selector-item/sprite-selector-item.jsx index bcccb7fe75355d5d4c010eb6cfd89a21810b46f8..458df186f94b4e4221d678511a99204ec16bad3d 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 CloseButton from '../close-button/close-button.jsx'; +import DeleteButton from '../delete-button/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'; @@ -48,9 +48,8 @@ const SpriteSelectorItem = props => ( ) : null} </div> {(props.selected && props.onDeleteButtonClick) ? ( - <CloseButton + <DeleteButton className={styles.deleteButton} - size={CloseButton.SIZE_SMALL} onClick={props.onDeleteButtonClick} /> ) : null } diff --git a/test/integration/sprites.test.js b/test/integration/sprites.test.js index 638c744a09004c5f70f6e8eb63002e7fbebff2bf..511d898ebce663ee4329166a4ca3430598b6d862 100644 --- a/test/integration/sprites.test.js +++ b/test/integration/sprites.test.js @@ -75,7 +75,7 @@ describe('Working with sprites', () => { test('Deleting by x button on sprite tile', async () => { await loadUri(uri); await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await clickXpath('//*[@aria-label="Close"]'); // Only visible close button is on the sprite + await clickXpath('//*[@aria-label="Delete"]'); // Only visible close button is on the sprite // Confirm that the stage has been switched to await findByText('Stage selected: no motion blocks'); const logs = await getLogs(); 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 2aa7a98297eadebbbee87c076edfb0f61108882a..f7f19434a6109bf1772637da5b6e80ccc1a04143 100644 --- a/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap +++ b/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap @@ -46,16 +46,20 @@ exports[`SpriteSelectorItemComponent matches snapshot when given a number and de </div> </div> <div - aria-label="Close" + aria-label="Delete" className="" onClick={[Function]} role="button" - tabIndex="0" + tabIndex={0} > - <img - className="" - src="test-file-stub" - /> + <div + className={undefined} + > + <img + className={undefined} + src="test-file-stub" + /> + </div> </div> <nav className="react-contextmenu" @@ -126,16 +130,20 @@ exports[`SpriteSelectorItemComponent matches snapshot when selected 1`] = ` </div> </div> <div - aria-label="Close" + aria-label="Delete" className="" onClick={[Function]} role="button" - tabIndex="0" + tabIndex={0} > - <img - className="" - src="test-file-stub" - /> + <div + className={undefined} + > + <img + className={undefined} + src="test-file-stub" + /> + </div> </div> <nav className="react-contextmenu" diff --git a/test/unit/components/sprite-selector-item.test.jsx b/test/unit/components/sprite-selector-item.test.jsx index 49e3fa705efc306529117ec1f88929281d533c78..fb103b4efc9e71211c0f99eac6e7f3339f1bd705 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 CloseButton from '../../../src/components/close-button/close-button'; +import DeleteButton from '../../../src/components/delete-button/delete-button'; describe('SpriteSelectorItemComponent', () => { let className; @@ -56,7 +56,7 @@ describe('SpriteSelectorItemComponent', () => { test('does not have a close box when not selected', () => { selected = false; const wrapper = shallowWithIntl(getComponent()); - expect(wrapper.find(CloseButton).exists()).toBe(false); + expect(wrapper.find(DeleteButton).exists()).toBe(false); }); test('triggers callback when Box component is clicked', () => { @@ -68,7 +68,7 @@ describe('SpriteSelectorItemComponent', () => { test('triggers callback when CloseButton component is clicked', () => { const wrapper = shallowWithIntl(getComponent()); - wrapper.find(CloseButton).simulate('click'); + wrapper.find(DeleteButton).simulate('click'); expect(onDeleteButtonClick).toHaveBeenCalled(); }); diff --git a/test/unit/containers/sprite-selector-item.test.jsx b/test/unit/containers/sprite-selector-item.test.jsx index f133c02a25789791f754e275edcfb58eb813c777..89018f5ef3631c0f8c620719cd4b36bd3d44746a 100644 --- a/test/unit/containers/sprite-selector-item.test.jsx +++ b/test/unit/containers/sprite-selector-item.test.jsx @@ -4,7 +4,7 @@ import configureStore from 'redux-mock-store'; import {Provider} from 'react-redux'; import SpriteSelectorItem from '../../../src/containers/sprite-selector-item'; -import CloseButton from '../../../src/components/close-button/close-button'; +import DeleteButton from '../../../src/components/delete-button/delete-button'; describe('SpriteSelectorItem Container', () => { const mockStore = configureStore(); @@ -52,7 +52,7 @@ describe('SpriteSelectorItem Container', () => { test('should delete the sprite', () => { const wrapper = mountWithIntl(getContainer()); - wrapper.find(CloseButton).simulate('click'); + wrapper.find(DeleteButton).simulate('click'); expect(onDeleteButtonClick).toHaveBeenCalledWith(1337); }); });