diff --git a/src/components/backpack/backpack.jsx b/src/components/backpack/backpack.jsx
index 0f7b0b89f7ea02a0f0e4fd2b6472debc75f82784..04cdc293798d3d2217f9eaed7299505db951c3a1 100644
--- a/src/components/backpack/backpack.jsx
+++ b/src/components/backpack/backpack.jsx
@@ -17,7 +17,7 @@ const dragTypeMap = {
     sprite: DragConstants.BACKPACK_SPRITE
 };
 
-const Backpack = ({contents, dragOver, dropAreaRef, error, expanded, loading, onToggle, onDelete}) => (
+const Backpack = ({containerRef, contents, dragOver, error, expanded, loading, onToggle, onDelete}) => (
     <div className={styles.backpackContainer}>
         <div
             className={styles.backpackHeader}
@@ -45,7 +45,7 @@ const Backpack = ({contents, dragOver, dropAreaRef, error, expanded, loading, on
         {expanded ? (
             <div
                 className={styles.backpackList}
-                ref={dropAreaRef}
+                ref={containerRef}
             >
                 {error ? (
                     <div className={styles.statusMessage}>
@@ -104,6 +104,7 @@ const Backpack = ({contents, dragOver, dropAreaRef, error, expanded, loading, on
 );
 
 Backpack.propTypes = {
+    containerRef: PropTypes.func,
     contents: PropTypes.arrayOf(PropTypes.shape({
         id: PropTypes.string,
         thumbnailUrl: PropTypes.string,
@@ -111,7 +112,6 @@ Backpack.propTypes = {
         name: PropTypes.string
     })),
     dragOver: PropTypes.bool,
-    dropAreaRef: PropTypes.func,
     error: PropTypes.bool,
     expanded: PropTypes.bool,
     loading: PropTypes.bool,
diff --git a/src/components/stage-selector/stage-selector.jsx b/src/components/stage-selector/stage-selector.jsx
index 50161bf8cbbfbc389ddcbd196201badfea408687..06894ae0187b9ff98c50b475b58246325f5a2098 100644
--- a/src/components/stage-selector/stage-selector.jsx
+++ b/src/components/stage-selector/stage-selector.jsx
@@ -40,6 +40,8 @@ const messages = defineMessages({
 const StageSelector = props => {
     const {
         backdropCount,
+        containerRef,
+        dragOver,
         fileInputRef,
         intl,
         selected,
@@ -60,9 +62,10 @@ const StageSelector = props => {
         <Box
             className={classNames(styles.stageSelector, {
                 [styles.isSelected]: selected,
-                [styles.raised]: raised,
+                [styles.raised]: raised || dragOver,
                 [styles.receivedBlocks]: receivedBlocks
             })}
+            componentRef={containerRef}
             onClick={onClick}
             onMouseEnter={onMouseEnter}
             onMouseLeave={onMouseLeave}
@@ -128,6 +131,8 @@ const StageSelector = props => {
 
 StageSelector.propTypes = {
     backdropCount: PropTypes.number.isRequired,
+    containerRef: PropTypes.func,
+    dragOver: PropTypes.bool,
     fileInputRef: PropTypes.func,
     intl: intlShape.isRequired,
     onBackdropFileUpload: PropTypes.func,
diff --git a/src/containers/backpack.jsx b/src/containers/backpack.jsx
index aedf2f35da1c84187386aae3e5132d7fbfad9372..e7303c145fb969ff5e226f68ff51b768f3b2da5b 100644
--- a/src/containers/backpack.jsx
+++ b/src/containers/backpack.jsx
@@ -11,11 +11,15 @@ import {
     spritePayload
 } from '../lib/backpack-api';
 import DragConstants from '../lib/drag-constants';
+import DropAreaHOC from '../lib/drop-area-hoc.jsx';
 
 import {connect} from 'react-redux';
 import storage from '../lib/storage';
 import VM from 'scratch-vm';
 
+const dragTypes = [DragConstants.COSTUME, DragConstants.SOUND, DragConstants.SPRITE];
+const DroppableBackpack = DropAreaHOC(dragTypes)(BackpackComponent);
+
 class Backpack extends React.Component {
     constructor (props) {
         super(props);
@@ -23,8 +27,7 @@ class Backpack extends React.Component {
             'handleDrop',
             'handleToggle',
             'handleDelete',
-            'refreshContents',
-            'setRef'
+            'refreshContents'
         ]);
         this.state = {
             dragOver: false,
@@ -46,29 +49,6 @@ class Backpack extends React.Component {
             storage._hasAddedBackpackSource = true;
         }
     }
-    componentWillReceiveProps (newProps) {
-        const dragTypes = [DragConstants.COSTUME, DragConstants.SOUND, DragConstants.SPRITE];
-        // If `dragging` becomes true, record the drop area rectangle
-        if (newProps.dragInfo.dragging && !this.props.dragInfo.dragging) {
-            this.dropAreaRect = this.ref && this.ref.getBoundingClientRect();
-        // If `dragging` becomes false, call the drop handler
-        } else if (!newProps.dragInfo.dragging && this.props.dragInfo.dragging && this.state.dragOver) {
-            this.handleDrop(this.props.dragInfo);
-            this.setState({dragOver: false});
-        }
-
-        // If a drag is in progress (currentOffset) and it matches the relevant drag types,
-        // test if the drag is within the drop area rect and set the state accordingly.
-        if (this.dropAreaRect && newProps.dragInfo.currentOffset && dragTypes.includes(newProps.dragInfo.dragType)) {
-            const {x, y} = newProps.dragInfo.currentOffset;
-            const {top, right, bottom, left} = this.dropAreaRect;
-            if (x > left && x < right && y > top && y < bottom) {
-                this.setState({dragOver: true});
-            } else {
-                this.setState({dragOver: false});
-            }
-        }
-    }
     handleToggle () {
         const newState = !this.state.expanded;
         this.setState({expanded: newState, offset: 0});
@@ -126,19 +106,15 @@ class Backpack extends React.Component {
                 });
         }
     }
-    setRef (ref) {
-        this.ref = ref;
-    }
     render () {
         return (
-            <BackpackComponent
+            <DroppableBackpack
                 contents={this.state.contents}
-                dragOver={this.state.dragOver}
-                dropAreaRef={this.setRef}
                 error={this.state.error}
                 expanded={this.state.expanded}
                 loading={this.state.loading}
                 onDelete={this.handleDelete}
+                onDrop={this.handleDrop}
                 onToggle={this.props.host ? this.handleToggle : null}
             />
         );
@@ -146,15 +122,6 @@ class Backpack extends React.Component {
 }
 
 Backpack.propTypes = {
-    dragInfo: PropTypes.shape({
-        currentOffset: PropTypes.shape({
-            x: PropTypes.number,
-            y: PropTypes.number
-        }),
-        dragType: PropTypes.string,
-        dragging: PropTypes.bool,
-        index: PropTypes.number
-    }),
     host: PropTypes.string,
     token: PropTypes.string,
     username: PropTypes.string,
@@ -181,7 +148,6 @@ const getTokenAndUsername = state => {
 
 const mapStateToProps = state => Object.assign(
     {
-        dragInfo: state.scratchGui.assetDrag,
         vm: state.scratchGui.vm
     },
     getTokenAndUsername(state)
diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx
index 99c233c7d8e7ea7b8a28f497274fe85da966948d..aeff4f2ad963de136829471b67d2dd551f45a0e4 100644
--- a/src/containers/stage-selector.jsx
+++ b/src/containers/stage-selector.jsx
@@ -7,6 +7,8 @@ import {connect} from 'react-redux';
 import {openBackdropLibrary} from '../reducers/modals';
 import {activateTab, COSTUMES_TAB_INDEX} from '../reducers/editor-tab';
 import {setHoveredSprite} from '../reducers/hovered-target';
+import DragConstants from '../lib/drag-constants';
+import DropAreaHOC from '../lib/drop-area-hoc.jsx';
 
 import StageSelectorComponent from '../components/stage-selector/stage-selector.jsx';
 
@@ -14,6 +16,9 @@ import backdropLibraryContent from '../lib/libraries/backdrops.json';
 import costumeLibraryContent from '../lib/libraries/costumes.json';
 import {handleFileUpload, costumeUpload} from '../lib/file-uploader.js';
 
+const dragTypes = [DragConstants.COSTUME, DragConstants.SOUND];
+const DroppableStage = DropAreaHOC(dragTypes)(StageSelectorComponent);
+
 class StageSelector extends React.Component {
     constructor (props) {
         super(props);
@@ -27,6 +32,7 @@ class StageSelector extends React.Component {
             'handleBackdropUpload',
             'handleMouseEnter',
             'handleMouseLeave',
+            'handleDrop',
             'setFileInput'
         ]);
     }
@@ -75,6 +81,13 @@ class StageSelector extends React.Component {
     handleMouseLeave () {
         this.props.dispatchSetHoveredSprite(null);
     }
+    handleDrop (dragInfo) {
+        if (dragInfo.dragType === DragConstants.COSTUME) {
+            this.props.vm.shareCostumeToTarget(dragInfo.index, this.props.id);
+        } else if (dragInfo.dragType === DragConstants.SOUND) {
+            this.props.vm.shareSoundToTarget(dragInfo.index, this.props.id);
+        }
+    }
     setFileInput (input) {
         this.fileInput = input;
     }
@@ -82,16 +95,16 @@ class StageSelector extends React.Component {
         const componentProps = omit(this.props, [
             'assetId', 'dispatchSetHoveredSprite', 'id', 'onActivateTab', 'onSelect']);
         return (
-            <StageSelectorComponent
+            <DroppableStage
                 fileInputRef={this.setFileInput}
                 onBackdropFileUpload={this.handleBackdropUpload}
                 onBackdropFileUploadClick={this.handleFileUploadClick}
                 onClick={this.handleClick}
+                onDrop={this.handleDrop}
                 onEmptyBackdropClick={this.handleEmptyBackdrop}
                 onMouseEnter={this.handleMouseEnter}
                 onMouseLeave={this.handleMouseLeave}
                 onSurpriseBackdropClick={this.handleSurpriseBackdrop}
-
                 {...componentProps}
             />
         );
diff --git a/src/lib/drop-area-hoc.jsx b/src/lib/drop-area-hoc.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..9f44293e88cdaab98dcd80b0a8cdd4fde915b646
--- /dev/null
+++ b/src/lib/drop-area-hoc.jsx
@@ -0,0 +1,88 @@
+import bindAll from 'lodash.bindall';
+import PropTypes from 'prop-types';
+import React from 'react';
+import omit from 'lodash.omit';
+import {connect} from 'react-redux';
+
+const DropAreaHOC = function (dragTypes) {
+    return function (WrappedComponent) {
+        class DropAreaWrapper extends React.Component {
+            constructor (props) {
+                super(props);
+                bindAll(this, [
+                    'setRef'
+                ]);
+
+                this.state = {
+                    dragOver: false
+                };
+
+                this.ref = null;
+                this.containerBox = null;
+            }
+
+            componentWillReceiveProps (newProps) {
+                // If `dragging` becomes true, record the drop area rectangle
+                if (newProps.dragInfo.dragging && !this.props.dragInfo.dragging) {
+                    this.dropAreaRect = this.ref && this.ref.getBoundingClientRect();
+                // If `dragging` becomes false, call the drop handler
+                } else if (!newProps.dragInfo.dragging && this.props.dragInfo.dragging && this.state.dragOver) {
+                    this.props.onDrop(this.props.dragInfo);
+                    this.setState({dragOver: false});
+                }
+
+                // If a drag is in progress (currentOffset) and it matches the relevant drag types,
+                // test if the drag is within the drop area rect and set the state accordingly.
+                if (this.dropAreaRect && newProps.dragInfo.currentOffset &&
+                    dragTypes.includes(newProps.dragInfo.dragType)) {
+                    const {x, y} = newProps.dragInfo.currentOffset;
+                    const {top, right, bottom, left} = this.dropAreaRect;
+                    if (x > left && x < right && y > top && y < bottom) {
+                        this.setState({dragOver: true});
+                    } else {
+                        this.setState({dragOver: false});
+                    }
+                }
+            }
+            setRef (el) {
+                this.ref = el;
+            }
+            render () {
+                const componentProps = omit(this.props, ['onDrop', 'dragInfo']);
+                return (
+                    <WrappedComponent
+                        containerRef={this.setRef}
+                        dragOver={this.state.dragOver}
+                        {...componentProps}
+                    />
+                );
+            }
+        }
+
+        DropAreaWrapper.propTypes = {
+            dragInfo: PropTypes.shape({
+                currentOffset: PropTypes.shape({
+                    x: PropTypes.number,
+                    y: PropTypes.number
+                }),
+                dragType: PropTypes.string,
+                dragging: PropTypes.bool,
+                index: PropTypes.number
+            }),
+            onDrop: PropTypes.func
+        };
+
+        const mapStateToProps = state => ({
+            dragInfo: state.scratchGui.assetDrag
+        });
+
+        const mapDispatchToProps = () => ({});
+
+        return connect(
+            mapStateToProps,
+            mapDispatchToProps
+        )(DropAreaWrapper);
+    };
+};
+
+export default DropAreaHOC;