diff --git a/package.json b/package.json
index 38ba8fbbeb99957d87f57d6630adbffd5b3474a0..e80b880a03cea23c56c8af788f5dc2b86c98d5dd 100644
--- a/package.json
+++ b/package.json
@@ -67,6 +67,7 @@
     "postcss-simple-vars": "^4.0.0",
     "prop-types": "^15.5.10",
     "react": "15.5.4",
+    "react-contextmenu": "2.6.5",
     "react-dom": "15.5.4",
     "react-draggable": "2.2.6",
     "react-intl": "2.3.0",
diff --git a/src/components/context-menu/context-menu.css b/src/components/context-menu/context-menu.css
new file mode 100644
index 0000000000000000000000000000000000000000..d74dc37204b04c2970c21c3c232ebe58dd65896a
--- /dev/null
+++ b/src/components/context-menu/context-menu.css
@@ -0,0 +1,29 @@
+@import "../../css/colors.css";
+@import "../../css/units.css";
+
+.context-menu {
+    min-width: 130px;
+    padding: 5px 0; /* The white strip at the top and bottom of the menu */
+    margin: 2px 0 0; /* To keep the menu below the cursor comfortably */
+    font-size: 0.85rem;
+    text-align: left;
+    background-color: #fff;
+    border: 1px solid $ui-pane-border;
+    border-radius: calc($space / 2);
+    box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.1);
+    pointer-events: none;
+    transition: opacity 0.2s ease;
+    z-index: 100;
+}
+
+.menu-item {
+    padding: 8px 12px;
+    white-space: nowrap;
+    cursor: pointer;
+    transition: 0.1s ease;
+}
+
+.menu-item:hover {
+    background: $motion-primary;
+    color: white;
+}
diff --git a/src/components/context-menu/context-menu.jsx b/src/components/context-menu/context-menu.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..7d33fe641ef436415298bc43c1caa77bad9ad649
--- /dev/null
+++ b/src/components/context-menu/context-menu.jsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import {ContextMenu, MenuItem} from 'react-contextmenu';
+
+import styles from './context-menu.css';
+
+const StyledContextMenu = props => (
+    <ContextMenu
+        {...props}
+        className={styles.contextMenu}
+    />
+);
+
+const StyledMenuItem = props => (
+    <MenuItem
+        {...props}
+        attributes={{className: styles.menuItem}}
+    />
+);
+
+export {
+    StyledContextMenu as ContextMenu,
+    StyledMenuItem as MenuItem
+};
diff --git a/src/components/sprite-selector-item/sprite-selector-item.jsx b/src/components/sprite-selector-item/sprite-selector-item.jsx
index d1be3c3dc33bb57c697539daa384203b92ca4f05..37e80217126cd251f3e1b09ca6987659f9cdae71 100644
--- a/src/components/sprite-selector-item/sprite-selector-item.jsx
+++ b/src/components/sprite-selector-item/sprite-selector-item.jsx
@@ -2,21 +2,25 @@ import classNames from 'classnames';
 import PropTypes from 'prop-types';
 import React from 'react';
 
-import Box from '../box/box.jsx';
 import CostumeCanvas from '../costume-canvas/costume-canvas.jsx';
 import CloseButton from '../close-button/close-button.jsx';
 import styles from './sprite-selector-item.css';
+import {ContextMenuTrigger} from 'react-contextmenu';
+import {ContextMenu, MenuItem} from '../context-menu/context-menu.jsx';
+import {FormattedMessage} from 'react-intl';
+
+// react-contextmenu requires unique id to match trigger and context menu
+let contextMenuId = 0;
 
 const SpriteSelectorItem = props => (
-    <Box
-        className={classNames(
-            props.className,
-            styles.spriteSelectorItem,
-            {
+    <ContextMenuTrigger
+        attributes={{
+            className: classNames(props.className, styles.spriteSelectorItem, {
                 [styles.isSelected]: props.selected
-            }
-        )}
-        onClick={props.onClick}
+            }),
+            onClick: props.onClick
+        }}
+        id={`${props.name}-${contextMenuId}`}
     >
         {props.selected ? (
             <CloseButton
@@ -24,7 +28,7 @@ const SpriteSelectorItem = props => (
                 size={CloseButton.SIZE_SMALL}
                 onClick={props.onDeleteButtonClick}
             />
-        ) : null }
+            ) : null }
         {props.costumeURL ? (
             <CostumeCanvas
                 className={styles.spriteImage}
@@ -32,9 +36,18 @@ const SpriteSelectorItem = props => (
                 url={props.costumeURL}
                 width={32}
             />
-        ) : null}
+            ) : null}
         <div className={styles.spriteName}>{props.name}</div>
-    </Box>
+        <ContextMenu id={`${props.name}-${contextMenuId++}`}>
+            <MenuItem onClick={props.onDeleteButtonClick}>
+                <FormattedMessage
+                    defaultMessage="delete"
+                    description="Menu item to delete in the right click menu"
+                    id="contextMenu.delete"
+                />
+            </MenuItem>
+        </ContextMenu>
+    </ContextMenuTrigger>
 );
 
 SpriteSelectorItem.propTypes = {
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 39146df349974556185db47203ad60931acb5c74..d30617f9aa25d3bcec9972f271d2cf7d76aeaf7d 100644
--- a/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap
+++ b/test/unit/components/__snapshots__/sprite-selector-item.test.jsx.snap
@@ -2,23 +2,14 @@
 
 exports[`SpriteSelectorItemComponent matches snapshot when selected 1`] = `
 <div
-  className="ponies undefined"
+  className="react-contextmenu-wrapper ponies undefined"
   onClick={[Function]}
-  style={
-    Object {
-      "alignContent": undefined,
-      "alignItems": undefined,
-      "alignSelf": undefined,
-      "flexBasis": undefined,
-      "flexDirection": undefined,
-      "flexGrow": undefined,
-      "flexShrink": undefined,
-      "flexWrap": undefined,
-      "height": undefined,
-      "justifyContent": undefined,
-      "width": undefined,
-    }
-  }
+  onContextMenu={[Function]}
+  onMouseDown={[Function]}
+  onMouseOut={[Function]}
+  onMouseUp={[Function]}
+  onTouchEnd={[Function]}
+  onTouchStart={[Function]}
 >
   <div
     className=""
@@ -39,5 +30,35 @@ exports[`SpriteSelectorItemComponent matches snapshot when selected 1`] = `
   >
     Pony sprite
   </div>
+  <nav
+    className="react-contextmenu"
+    onContextMenu={[Function]}
+    onMouseLeave={[Function]}
+    role="menu"
+    style={
+      Object {
+        "opacity": 0,
+        "pointerEvents": "none",
+        "position": "fixed",
+      }
+    }
+    tabIndex="-1"
+  >
+    <div
+      aria-disabled="false"
+      aria-orientation={null}
+      className="react-contextmenu-item"
+      onClick={[Function]}
+      onMouseLeave={[Function]}
+      onMouseMove={[Function]}
+      onTouchEnd={[Function]}
+      role="menuitem"
+      tabIndex="-1"
+    >
+      <span>
+        delete
+      </span>
+    </div>
+  </nav>
 </div>
 `;
diff --git a/test/unit/components/sprite-selector-item.test.jsx b/test/unit/components/sprite-selector-item.test.jsx
index 8059b7152f973f9090aee8c019c8d260f61f1bb6..fe0b1de5238b5076e9938da8303dfb714023212c 100644
--- a/test/unit/components/sprite-selector-item.test.jsx
+++ b/test/unit/components/sprite-selector-item.test.jsx
@@ -1,11 +1,10 @@
 /* eslint-env jest */
 import React from 'react'; // eslint-disable-line no-unused-vars
-import {shallow} from 'enzyme';
+import {mountWithIntl, shallowWithIntl, componentWithIntl} from '../../helpers/intl-helpers';
 // eslint-disable-next-line no-unused-vars
 import SpriteSelectorItemComponent from '../../../src/components/sprite-selector-item/sprite-selector-item';
 import CostumeCanvas from '../../../src/components/costume-canvas/costume-canvas';
 import CloseButton from '../../../src/components/close-button/close-button'; // eslint-disable-line no-unused-vars
-import renderer from 'react-test-renderer';
 
 describe('SpriteSelectorItemComponent', () => {
     let className;
@@ -36,36 +35,46 @@ describe('SpriteSelectorItemComponent', () => {
     });
 
     test('matches snapshot when selected', () => {
-        const component = renderer.create(getComponent());
+        const component = componentWithIntl(getComponent());
         expect(component.toJSON()).toMatchSnapshot();
     });
 
     test('does not have a close box when not selected', () => {
         selected = false;
-        const componentShallowWrapper = shallow(getComponent());
-        expect(componentShallowWrapper.find(CloseButton).exists()).toBe(false);
+        const wrapper = shallowWithIntl(getComponent());
+        expect(wrapper.find(CloseButton).exists()).toBe(false);
     });
 
     test('triggers callback when Box component is clicked', () => {
-        const componentShallowWrapper = shallow(getComponent());
-        componentShallowWrapper.simulate('click');
+        // Use `mount` here because of the way ContextMenuTrigger consumes onClick
+        const wrapper = mountWithIntl(getComponent());
+        wrapper.simulate('click');
         expect(onClick).toHaveBeenCalled();
     });
 
     test('triggers callback when CloseButton component is clicked', () => {
-        const componentShallowWrapper = shallow(getComponent());
-        componentShallowWrapper.find(CloseButton).simulate('click');
+        const wrapper = shallowWithIntl(getComponent());
+        wrapper.find(CloseButton).simulate('click');
         expect(onDeleteButtonClick).toHaveBeenCalled();
     });
 
     test('creates a CostumeCanvas when a costume url is defined', () => {
-        const componentShallowWrapper = shallow(getComponent());
-        expect(componentShallowWrapper.find(CostumeCanvas).exists()).toBe(true);
+        const wrapper = shallowWithIntl(getComponent());
+        expect(wrapper.find(CostumeCanvas).exists()).toBe(true);
     });
 
     test('does not create a CostumeCanvas when a costume url is null', () => {
         costumeURL = null;
-        const componentShallowWrapper = shallow(getComponent());
-        expect(componentShallowWrapper.find(CostumeCanvas).exists()).toBe(false);
+        const wrapper = shallowWithIntl(getComponent());
+        expect(wrapper.find(CostumeCanvas).exists()).toBe(false);
+    });
+
+    test('it has a context menu with delete menu item and callback', () => {
+        const wrapper = mountWithIntl(getComponent());
+        const contextMenu = wrapper.find('ContextMenu');
+        expect(contextMenu.exists()).toBe(true);
+
+        contextMenu.find('[children="delete"]').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 d5a822996b6a4f6b4958271bd4fa0fb19094f822..1efd40cb7cc05a26f9521dee06ad3935225fd7e8 100644
--- a/test/unit/containers/sprite-selector-item.test.jsx
+++ b/test/unit/containers/sprite-selector-item.test.jsx
@@ -1,6 +1,6 @@
 /* eslint-env jest */
 import React from 'react'; // eslint-disable-line no-unused-vars
-import {mount} from 'enzyme';
+import {mountWithIntl} from '../../helpers/intl-helpers';
 import configureStore from 'redux-mock-store';
 import {Provider} from 'react-redux'; // eslint-disable-line no-unused-vars
 
@@ -43,7 +43,7 @@ describe('SpriteSelectorItem Container', () => {
     });
 
     test('should confirm if the user really wants to delete the sprite', () => {
-        const wrapper = mount(getContainer());
+        const wrapper = mountWithIntl(getContainer());
         wrapper.find(CloseButton).simulate('click');
         expect(global.confirm).toHaveBeenCalled();
         expect(onDeleteButtonClick).toHaveBeenCalledWith(1337);
@@ -51,7 +51,7 @@ describe('SpriteSelectorItem Container', () => {
 
     test('should not delete the sprite if the user cancels', () => {
         global.confirm = jest.fn(() => false);
-        const wrapper = mount(getContainer());
+        const wrapper = mountWithIntl(getContainer());
         wrapper.find(CloseButton).simulate('click');
         expect(global.confirm).toHaveBeenCalled();
         expect(onDeleteButtonClick).not.toHaveBeenCalled();