diff --git a/static/app-strings.json b/static/app-strings.json
index 1ced8769f..9d0121e3a 100644
--- a/static/app-strings.json
+++ b/static/app-strings.json
@@ -1218,4 +1218,4 @@
   "Check your rewards page to see if you qualify for paid content reimbursement. Only content in this section qualifies.": "Check your rewards page to see if you qualify for paid content reimbursement. Only content in this section qualifies.",
   "blocked channels": "blocked channels",
   "%count% %channels%. ": "%count% %channels%. "
-}
\ No newline at end of file
+}
diff --git a/ui/effects/use-drag-drop.js b/ui/effects/use-drag-drop.js
new file mode 100644
index 000000000..78d524a0b
--- /dev/null
+++ b/ui/effects/use-drag-drop.js
@@ -0,0 +1,97 @@
+import React from 'react';
+
+const LISTENER = {
+  ADD: 'add',
+  REMOVE: 'remove',
+};
+
+const DRAG_TYPES = {
+  END: 'dragend',
+  START: 'dragstart',
+  ENTER: 'dragenter',
+  LEAVE: 'dragleave',
+};
+
+const DRAG_SCORE = {
+  [DRAG_TYPES.ENTER]: 1,
+  [DRAG_TYPES.LEAVE]: -1,
+};
+
+const DRAG_STATE = {
+  [DRAG_TYPES.END]: false,
+  [DRAG_TYPES.START]: true,
+};
+
+// Returns simple detection for global drag-drop
+export default function useFetched() {
+  const [drag, setDrag] = React.useState(false);
+  const [drop, setDrop] = React.useState(null);
+
+  React.useEffect(() => {
+    let dragCount = 0;
+    let draggingElement = false;
+
+    // Handle file drop
+    const handleDropEvent = event => {
+      // Ignore non file types ( html elements / text )
+      if (!draggingElement) {
+        event.stopPropagation();
+        event.preventDefault();
+        // Get files
+        const files = event.dataTransfer.files;
+        // Store files in state
+        if (files.length && files.length > 0) {
+          setDrop(files);
+        }
+      }
+      // Reset state ( hide drop zone )
+      dragCount = 0;
+      setDrag(false);
+    };
+
+    // Drag event for non files type ( html elements / text )
+    const handleDragElementEvent = event => {
+      draggingElement = DRAG_STATE[event.type];
+    };
+
+    // Drag events
+    const handleDragEvent = event => {
+      event.stopPropagation();
+      event.preventDefault();
+      // Prevent multiple drop areas
+      dragCount += DRAG_SCORE[event.type];
+      // Dragged file enters the drop area
+      if (dragCount === 1 && !draggingElement && event.type === DRAG_TYPES.ENTER) {
+        setDrag(true);
+      }
+      // Dragged file leaves the drop area
+      if (dragCount === 0 && event.type === DRAG_TYPES.LEAVE) {
+        setDrag(false);
+      }
+    };
+
+    // Register / Unregister listeners
+    const handleEventListeners = event => {
+      const action = `${event}EventListener`;
+      // Handle drop event
+      document[action]('drop', handleDropEvent);
+      // Handle drag events
+      document[action](DRAG_TYPES.ENTER, handleDragEvent);
+      document[action](DRAG_TYPES.LEAVE, handleDragEvent);
+      // Handle non files drag events
+      document[action](DRAG_TYPES.END, handleDragElementEvent);
+      document[action](DRAG_TYPES.START, handleDragElementEvent);
+    };
+    // On component mounted:
+    // Register event listeners
+    handleEventListeners(LISTENER.ADD);
+
+    // On component unmounted:
+    return () => {
+      // Unregister event listeners
+      handleEventListeners(LISTENER.REMOVE);
+    };
+  }, []);
+
+  return { drag, drop };
+}