diff --git a/packages/component-sortable-list/package.json b/packages/component-sortable-list/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..3ff0d8c6be2c0d7dd64296fe7e9c374ab9ff9498
--- /dev/null
+++ b/packages/component-sortable-list/package.json
@@ -0,0 +1,12 @@
+{
+  "name": "pubsweet-component-sortable-list",
+  "version": "0.0.1",
+  "main": "src",
+  "license": "MIT",
+  "dependencies": {
+    "react": "^15.6.1",
+    "react-dnd": "^2.5.4",
+    "react-dom": "^15.6.1",
+    "recompose": "^0.26.0"
+  }
+}
diff --git a/packages/component-sortable-list/src/components/SortableList.js b/packages/component-sortable-list/src/components/SortableList.js
new file mode 100644
index 0000000000000000000000000000000000000000..e454020635d88c8712efb97209a30001803a3227
--- /dev/null
+++ b/packages/component-sortable-list/src/components/SortableList.js
@@ -0,0 +1,133 @@
+import React from 'react'
+import { pick } from 'lodash'
+import { compose } from 'recompose'
+import { findDOMNode } from 'react-dom'
+import { DragSource, DropTarget } from 'react-dnd'
+
+const itemSource = {
+  beginDrag(props) {
+    return pick(props, props.beginDragProps)
+  },
+}
+
+const itemTarget = {
+  hover({ moveItem, index, listId }, monitor, component) {
+    const { index: dragIndex, listId: toListId } = monitor.getItem()
+    const hoverIndex = index
+
+    if (listId !== toListId) {
+      return
+    }
+
+    // Don't replace items with themselves
+    if (dragIndex === hoverIndex) {
+      return
+    }
+
+    const hoverBoundingRect = findDOMNode(component).getBoundingClientRect() // eslint-disable-line
+    const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
+    const clientOffset = monitor.getClientOffset()
+    const hoverClientY = clientOffset.y - hoverBoundingRect.top
+
+    if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
+      return
+    }
+
+    if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
+      return
+    }
+    if (typeof moveItem === 'function') {
+      moveItem(dragIndex, hoverIndex)
+    }
+    monitor.getItem().index = hoverIndex
+  },
+  drop({ dropItem, ...restProps }, monitor) {
+    if (dropItem && typeof dropItem === 'function')
+      dropItem(restProps, monitor.getItem())
+  },
+}
+
+const Item = ({
+  connectDragPreview,
+  connectDragSource,
+  connectDropTarget,
+  listItem,
+  dragHandle,
+  ...rest
+}) =>
+  dragHandle
+    ? connectDragPreview(
+        connectDropTarget(
+          <div style={{ flex: 1 }}>
+            {React.createElement(listItem, {
+              ...rest,
+              dragHandle: connectDragSource(
+                <div style={{ display: 'flex' }}>
+                  {React.createElement(dragHandle)}
+                </div>,
+              ),
+            })}
+          </div>,
+        ),
+      )
+    : connectDropTarget(
+        connectDragSource(
+          <div style={{ flex: 1 }}>{React.createElement(listItem, rest)}</div>,
+        ),
+      )
+
+const DecoratedItem = compose(
+  DropTarget('item', itemTarget, (connect, monitor) => ({
+    connectDropTarget: connect.dropTarget(),
+    isOver: monitor.isOver(),
+  })),
+  DragSource('item', itemSource, (connect, monitor) => ({
+    connectDragSource: connect.dragSource(),
+    connectDragPreview: connect.dragPreview(),
+    isDragging: monitor.isDragging(),
+  })),
+)(Item)
+
+const SortableList = ({
+  items,
+  itemKey = 'id',
+  moveItem,
+  listItem,
+  dragHandle,
+  editItem,
+  ...rest
+}) => (
+  <div>
+    {items.map((item, i) => (
+      <DecoratedItem
+        dragHandle={dragHandle}
+        index={i}
+        key={item[itemKey]}
+        listItem={listItem}
+        moveItem={moveItem}
+        {...item}
+        {...rest}
+      />
+    ))}
+  </div>
+)
+
+// helper function for sortable lists
+SortableList.moveItem = (items, dragIndex, hoverIndex) => {
+  if (dragIndex <= hoverIndex) {
+    return [
+      ...items.slice(0, dragIndex),
+      items[hoverIndex],
+      items[dragIndex],
+      ...items.slice(hoverIndex + 1),
+    ]
+  }
+  return [
+    ...items.slice(0, hoverIndex),
+    items[dragIndex],
+    items[hoverIndex],
+    ...items.slice(dragIndex + 1),
+  ]
+}
+
+export default SortableList
diff --git a/packages/component-sortable-list/src/components/SortableList.md b/packages/component-sortable-list/src/components/SortableList.md
new file mode 100644
index 0000000000000000000000000000000000000000..041ee606fb2ded7ba45bd5597431835db99da112
--- /dev/null
+++ b/packages/component-sortable-list/src/components/SortableList.md
@@ -0,0 +1,115 @@
+A sortable list implemented with `react-dnd`.
+
+## Props
+
+|      Prop      |                                                                 Description                                                                  | Required | Default |      Type       |
+| :------------: | :------------------------------------------------------------------------------------------------------------------------------------------: | :------: | :-----: | :-------------: |
+|     items      |                                                       The items of the sortable list.                                                        |   true   |   []    |      Array      |
+|    itemKey     |                                                 Value used for key when mapping over items.                                                  |   true   |  'id'   |     string      |
+|    listItem    | A React component that will be rendered for each item of the list. Receives `isDragging`, `isOver` and all other props from the items array. |   true   |  none   | React component |
+|    moveItem    |       Function to be called when moving an item through the list. SortableList will provide the dragIndex of hoverIndex of the items.        |   true   |  none   |    function     |
+|   dragHandle   |                            A React component for the drag handle. If not present, the whole item can be dragged.                             |  false   |  none   | React component |
+|    dropItem    |                            Function to be called when dropping an item. The index of the dragged item is passed.                             |  false   |  none   |    function     |
+| beginDragProps |                                      Array of keys to pick from the dragged object when beginning drag.                                      |  false   |   []    |  Array(string)  |
+
+## Usage
+
+This component should be used in a React-DnD `DragDropContext` or `DragDropContextProvider`. Make sure you have `react-dnd-html5-backend` installed and wrap the parent component with `DragDropContext` decorator or add the `DragDropContextProvider` in your root component.
+
+```js
+import HTML5Backend from 'react-dnd-html5-backend'
+import { DragDropContext } from 'react-dnd'
+
+class YourApp {
+  /* ... */
+}
+
+export default DragDropContext(HTML5Backend)(YourApp)
+```
+
+or
+
+```js
+import HTML5Backend from 'react-dnd-html5-backend'
+import { DragDropContextProvider } from 'react-dnd'
+
+export default class YourApp {
+  render() {
+    return (
+      <DragDropContextProvider backend={HTML5Backend}>
+      /* ... */
+      </DragDropContextProvider>
+    )
+  }
+}
+```
+
+### Pass in a list of users
+
+```js
+const items = [
+  {firstName: 'John', lastName: 'Doe'},
+  {firstName: 'Michael', lastName: 'Jackson'},
+  {firstName: 'David', lastName: 'Blaine'},
+]
+
+const Item = ({ isOver, isDragging, ...rest }) =>
+  <div>`${rest.firstName} ${rest.lastName}`</div>
+
+<SortableList
+  items={items}
+  listItem={Item}
+  moveItem={(dragIndex, hoverIndex) => change items}
+  />
+```
+
+### With custom drag handle
+
+```js
+const DragHandle = () => <div>Drag me!</div>
+
+const ItemWithDragHandle = ({ dragHandle, ...rest }) => <div>
+    {dragHandle}
+    <span>Rest of the content.</span>
+  </div>
+
+<SortableList
+  ...
+  listItem={ItemWithDragHandle}
+  dragHandle={DragHandle}
+  ...
+  />
+```
+
+### How to move items around
+
+To move items of the parent container whenever `moveItem` function is called we can use the `SortableList.moveItem` helper. More info in the example below.
+
+```js
+const Container = ({ moveItem, items }) => (
+  <div>
+    ...
+    <SortableList items={items} listItem={Item} moveItem={moveItem} />
+    ...
+  </div>
+)
+```
+
+Enhanced using recompose
+
+```js
+const MoveExample = compose(
+  withState('items', 'setItems', [
+    { name: 'John' },
+    { name: 'Nancy' },
+    { name: 'Adam' },
+  ]),
+  withHandlers({
+    moveItem: ({ setItems, items }) => (dragIndex, hoverIndex) => {
+      setItems(prevItems =>
+        SortableList.moveItem(prevItems, dragIndex, hoverIndex),
+      )
+    },
+  }),
+)(Container)
+```
diff --git a/packages/component-sortable-list/src/components/index.js b/packages/component-sortable-list/src/components/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..5468a1bf42a9d588ee1f770d1d7c1b917ed17ca5
--- /dev/null
+++ b/packages/component-sortable-list/src/components/index.js
@@ -0,0 +1 @@
+export { default as SortableList } from './SortableList'
diff --git a/packages/component-sortable-list/src/index.js b/packages/component-sortable-list/src/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..8d52f148e8c8927db1d86494ca404451da5a917d
--- /dev/null
+++ b/packages/component-sortable-list/src/index.js
@@ -0,0 +1,5 @@
+module.exports = {
+  client: {
+    components: [() => require('./components')],
+  },
+}
diff --git a/packages/components-faraday/src/components/AuthorList/AuthorList.js b/packages/components-faraday/src/components/AuthorList/AuthorList.js
index 382931818f802c5cc66b6d90e4f256f2e1d5a13e..9b00dd834522826565e79cd7d4a8a24f17e49b84 100644
--- a/packages/components-faraday/src/components/AuthorList/AuthorList.js
+++ b/packages/components-faraday/src/components/AuthorList/AuthorList.js
@@ -11,7 +11,7 @@ import {
   withState,
 } from 'recompose'
 import { change as changeForm } from 'redux-form'
-import { SortableList } from 'pubsweet-components-faraday/src/components'
+import { SortableList } from 'pubsweet-component-sortable-list/src/components'
 
 import { addAuthor } from '../../redux/authors'