diff --git a/__tests__/src/actions/companionWindow.test.js b/__tests__/src/actions/companionWindow.test.js
index 9cd364ea793266ba1d506857aea4364ea498b99c..183949b736913b742482af63cadf42810fb99f51 100644
--- a/__tests__/src/actions/companionWindow.test.js
+++ b/__tests__/src/actions/companionWindow.test.js
@@ -9,7 +9,20 @@ describe('companionWindow actions', () => {
         position: 'right',
         foo: 'bar',
       };
-      const action = actions.addCompanionWindow(payload);
+      const mockState = {
+        windows: {
+          abc123: { companionWindowIds: [] },
+        },
+        companionWindows: {},
+      };
+
+      const mockDispatch = jest.fn(() => ({}));
+      const mockGetState = jest.fn(() => mockState);
+      const thunk = actions.addCompanionWindow('abc123', payload);
+      thunk(mockDispatch, mockGetState);
+
+      const action = mockDispatch.mock.calls[0][0];
+
       expect(action.type).toBe(ActionTypes.ADD_COMPANION_WINDOW);
       expect(action.payload).toMatchObject(payload);
       expect(action.payload.id).toMatch(/cw-.*/);
@@ -18,14 +31,42 @@ describe('companionWindow actions', () => {
     it('should set the correct default values', () => {
       const payload = {};
       const defaults = { foo: 'bar' };
-      const action = actions.addCompanionWindow(payload, defaults);
+
+      const mockState = {
+        windows: {
+          abc123: { companionWindowIds: [] },
+        },
+        companionWindows: {},
+      };
+
+      const mockDispatch = jest.fn(() => ({}));
+      const mockGetState = jest.fn(() => mockState);
+      const thunk = actions.addCompanionWindow('abc123', payload, defaults);
+      thunk(mockDispatch, mockGetState);
+
+      const action = mockDispatch.mock.calls[0][0];
+
       expect(action.payload.foo).toBe('bar');
     });
 
     it('should generate a new companionWindow ID', () => {
       const payload = {};
 
-      expect(actions.addCompanionWindow(payload).id).toEqual(
+      const mockState = {
+        windows: {
+          abc123: { companionWindowIds: [] },
+        },
+        companionWindows: {},
+      };
+
+      const mockDispatch = jest.fn(() => ({}));
+      const mockGetState = jest.fn(() => mockState);
+
+      const thunk = actions.addCompanionWindow('abc123', payload);
+      thunk(mockDispatch, mockGetState);
+      const action = mockDispatch.mock.calls[0][0];
+
+      expect(action.id).toEqual(
         expect.stringMatching(/^cw-\w+-\w+/),
       );
     });
@@ -33,45 +74,17 @@ describe('companionWindow actions', () => {
 
   describe('updateCompanionWindow', () => {
     it('should return correct action object', () => {
-      const mockState = {
-        windows: {
-          abc123: {
-            companionWindowIds: ['cw-1', 'cw-2'],
-          },
-        },
-        companionWindows: {
-          'cw-1': { position: 'right' },
-          'cw-2': { position: 'not-right' },
-        },
-      };
-
       const payload = {
         content: 'info',
         position: 'right',
+        foo: 'bar',
       };
-      const thunk = actions.updateCompanionWindow('abc123', 'cw-123', payload);
-
-      const mockDispatch = jest.fn(() => {});
-      const mockGetState = jest.fn(() => mockState);
-
-      thunk(mockDispatch, mockGetState);
 
-      expect(mockDispatch).toHaveBeenNthCalledWith(1, {
-        type: ActionTypes.REMOVE_COMPANION_WINDOW,
-        id: 'cw-1',
-      });
+      const action = actions.updateCompanionWindow('abc123', 'cw-123', payload);
 
-      expect(mockDispatch).toHaveBeenNthCalledWith(2, {
-        type: ActionTypes.UPDATE_WINDOW,
-        id: 'abc123',
-        payload: { companionWindowIds: ['cw-2'] },
-      });
-
-      const updateCompanionWindowAction = mockDispatch.mock.calls[2][0];
-
-      expect(updateCompanionWindowAction.type).toBe(ActionTypes.UPDATE_COMPANION_WINDOW);
-      expect(updateCompanionWindowAction.id).toBe('cw-123');
-      expect(updateCompanionWindowAction.payload).toEqual(payload);
+      expect(action.type).toBe(ActionTypes.UPDATE_COMPANION_WINDOW);
+      expect(action.id).toBe('cw-123');
+      expect(action.payload).toEqual(payload);
     });
   });
 
@@ -82,74 +95,4 @@ describe('companionWindow actions', () => {
       expect(action.id).toBe('cw-123');
     });
   });
-
-  describe('popOutCompanionWindow', () => {
-    it('returns a thunk which dispatches the appropriate actions', () => {
-      const mockState = {
-        windows: {
-          abc123: {
-            companionWindowIds: ['cw-1', 'cw-2'],
-          },
-        },
-        companionWindows: {
-          'cw-1': { position: 'right' },
-          'cw-2': { position: 'not-right' },
-        },
-      };
-      const mockDispatch = jest.fn(() => ({ id: 'cw-3' }));
-      const mockGetState = jest.fn(() => mockState);
-      const windowId = 'abc123';
-      const panelType = 'info';
-      const position = 'right';
-      const thunk = actions.popOutCompanionWindow(windowId, panelType, position);
-
-      expect(typeof thunk).toEqual('function');
-      thunk(mockDispatch, mockGetState);
-
-      expect(mockDispatch).toHaveBeenNthCalledWith(1, {
-        type: ActionTypes.REMOVE_COMPANION_WINDOW,
-        id: 'cw-1',
-      });
-
-      const addCompanionWindowAction = mockDispatch.mock.calls[1][0];
-      expect(addCompanionWindowAction.type).toBe(ActionTypes.ADD_COMPANION_WINDOW);
-      expect(addCompanionWindowAction.payload).toMatchObject({ content: 'info', position: 'right' });
-      expect(addCompanionWindowAction.id.startsWith('cw-')).toBe(true);
-
-      expect(mockDispatch).toHaveBeenNthCalledWith(3, {
-        type: ActionTypes.UPDATE_WINDOW,
-        id: 'abc123',
-        payload: { companionWindowIds: ['cw-2', 'cw-3'] },
-      });
-    });
-
-    it('sets the window sidebar panel type if the companion window appears in the left position', () => {
-      const mockState = {
-        windows: {
-          abc123: { companionWindowIds: [] },
-        },
-        companionWindows: {},
-      };
-
-      const mockDispatch = jest.fn(() => ({ id: 'cw-3' }));
-      const mockGetState = jest.fn(() => mockState);
-      const windowId = 'abc123';
-      const panelType = 'info';
-      const position = 'left';
-      const thunk = actions.popOutCompanionWindow(windowId, panelType, position);
-      thunk(mockDispatch, mockGetState);
-
-      expect(mockDispatch).toHaveBeenNthCalledWith(1, {
-        type: ActionTypes.SET_WINDOW_SIDE_BAR_PANEL,
-        windowId: 'abc123',
-        panelType: 'info',
-      });
-
-      expect(mockDispatch).toHaveBeenNthCalledWith(2, {
-        type: ActionTypes.UPDATE_WINDOW,
-        id: 'abc123',
-        payload: { companionAreaOpen: true },
-      });
-    });
-  });
 });
diff --git a/__tests__/src/reducers/windows.test.js b/__tests__/src/reducers/windows.test.js
index fd0dbf384bfc2a1a14e882a76c9989d8a97de308..d39aad6e4f52231ac67ffe8649af5fbfbf33ae02 100644
--- a/__tests__/src/reducers/windows.test.js
+++ b/__tests__/src/reducers/windows.test.js
@@ -245,4 +245,52 @@ describe('windows reducer', () => {
       },
     });
   });
+
+  it('should handle ADD_COMPANION_WINDOW', () => {
+    // on the right, just tacks the new id on
+    expect(windowsReducer({
+      abc123: {
+        id: 'abc123',
+        companionWindowIds: ['123'],
+      },
+    }, {
+      type: ActionTypes.ADD_COMPANION_WINDOW,
+      id: 'xyz',
+      windowId: 'abc123',
+      payload: {
+        position: 'right',
+      },
+    })).toEqual({
+      abc123: {
+        id: 'abc123',
+        companionWindowIds: ['123', 'xyz'],
+      },
+    });
+
+    // on the left, replaces all ids of windows in that position and sets some additional properties
+    expect(windowsReducer({
+      abc123: {
+        id: 'abc123',
+        companionWindowIds: ['left123'],
+      },
+    }, {
+      type: ActionTypes.ADD_COMPANION_WINDOW,
+      id: 'xyz',
+      windowId: 'abc123',
+      companionWindows: {
+        left123: { position: 'left' },
+      },
+      payload: {
+        content: 'content',
+        position: 'left',
+      },
+    })).toEqual({
+      abc123: {
+        id: 'abc123',
+        companionAreaOpen: true,
+        sideBarPanel: 'content',
+        companionWindowIds: ['xyz'],
+      },
+    });
+  });
 });
diff --git a/src/containers/WindowSideBarButtons.js b/src/containers/WindowSideBarButtons.js
index a485d635581948b26a6d895846da68ce64a609a0..96116259a8413b5a9e1d211abb9b4bec3de0c60a 100644
--- a/src/containers/WindowSideBarButtons.js
+++ b/src/containers/WindowSideBarButtons.js
@@ -19,8 +19,8 @@ import { WindowSideBarButtons } from '../components/WindowSideBarButtons';
  * @private
  */
 const mapDispatchToProps = (dispatch, { windowId }) => ({
-  addCompanionWindow: panelType => dispatch(
-    actions.popOutCompanionWindow(windowId, panelType, 'left'),
+  addCompanionWindow: content => dispatch(
+    actions.addCompanionWindow(windowId, { content, position: 'left' }),
   ),
 });
 
diff --git a/src/state/actions/companionWindow.js b/src/state/actions/companionWindow.js
index 81ea10c5f162c36547a46dac7c9e5781e1c210cb..044bbc648e4e5811b361fa1b2534d186859f9b2d 100644
--- a/src/state/actions/companionWindow.js
+++ b/src/state/actions/companionWindow.js
@@ -1,6 +1,6 @@
 import uuid from 'uuid/v4';
 import ActionTypes from './action-types';
-import { updateWindow, setCompanionAreaOpen, setWindowSideBarPanel } from './window';
+import { updateWindow } from './window';
 
 const defaultProps = {
   content: null,
@@ -8,29 +8,28 @@ const defaultProps = {
 };
 
 /** */
-export function addCompanionWindow(payload, defaults = defaultProps) {
-  const id = `cw-${uuid()}`;
-
-  return {
-    type: ActionTypes.ADD_COMPANION_WINDOW,
-    id,
-    payload: { ...defaults, ...payload, id },
+export function addCompanionWindow(windowId, payload, defaults = defaultProps) {
+  return (dispatch, getState) => {
+    const { companionWindows } = getState();
+    const id = `cw-${uuid()}`;
+
+    dispatch({
+      type: ActionTypes.ADD_COMPANION_WINDOW,
+      id,
+      windowId,
+      companionWindows,
+      payload: { ...defaults, ...payload, id },
+    });
   };
 }
 
 /** */
 export function updateCompanionWindow(windowId, id, payload) {
-  return (dispatch, getState) => {
-    if (payload.position === 'left') {
-      const { windows, companionWindows } = getState();
-      const { companionWindowIds } = windows[windowId];
-
-      companionWindowIds
-        .filter(cwid => companionWindows[cwid].position === payload.position)
-        .map(cwid => closeCompanionWindow(windowId, cwid)(dispatch, getState));
-    }
-
-    dispatch({ type: ActionTypes.UPDATE_COMPANION_WINDOW, id, payload });
+  return {
+    type: ActionTypes.UPDATE_COMPANION_WINDOW,
+    windowId,
+    id,
+    payload,
   };
 }
 
@@ -50,46 +49,3 @@ export function closeCompanionWindow(windowId, companionWindowId) {
     dispatch(updateWindow(windowId, { companionWindowIds }));
   };
 }
-
-/**
- * popOutCompanionWindow - action creator
- *
- * @param  {String} windowId
- * @param  {String} panelType The type of panel content to be rendered
- *                            in the companion window (e.g. info, canvas_navigation)
- * @param  {String} position The position of the companion window to
- *                           set content for (e.g. right, bottom)
- * @memberof ActionCreators
- */
-export function popOutCompanionWindow(windowId, panelType, position) {
-  return (dispatch, getState) => {
-    const { windows, companionWindows } = getState();
-    const { companionWindowIds } = windows[windowId];
-
-    if (position === 'left') {
-      companionWindowIds
-        .filter(id => companionWindows[id].position === position)
-        .map(id => dispatch(removeCompanionWindow(id)));
-
-      dispatch(setWindowSideBarPanel(windowId, panelType));
-
-      dispatch(setCompanionAreaOpen(windowId, true));
-    }
-
-    const action = dispatch(addCompanionWindow({ content: panelType, position }));
-
-    const companionWindowId = action.id;
-    let existingCompanionWindowIds;
-
-    if (position === 'left') {
-      existingCompanionWindowIds = companionWindowIds
-        .filter(id => (companionWindows[id].position !== position));
-    } else {
-      existingCompanionWindowIds = companionWindowIds;
-    }
-
-    dispatch(updateWindow(windowId, {
-      companionWindowIds: existingCompanionWindowIds.concat([companionWindowId]),
-    }));
-  };
-}
diff --git a/src/state/reducers/windows.js b/src/state/reducers/windows.js
index d38020744ec8beb66428215a6dd7d979dd587e90..597ba21112fe54eb027bee6829b3904319528ff6 100644
--- a/src/state/reducers/windows.js
+++ b/src/state/reducers/windows.js
@@ -96,6 +96,31 @@ export const windowsReducer = (state = {}, action) => {
       return setCanvasIndex(state, action.windowId, currentIndex => currentIndex - 1);
     case ActionTypes.SET_CANVAS:
       return setCanvasIndex(state, action.windowId, currentIndex => action.canvasIndex);
+    case ActionTypes.ADD_COMPANION_WINDOW:
+      if (action.payload.position === 'left') {
+        const { companionWindowIds } = state[action.windowId];
+        const { companionWindows } = action;
+        const newCompanionWindowIds = companionWindowIds
+          .filter(id => companionWindows[id].position !== action.payload.position);
+
+        return {
+          ...state,
+          [action.windowId]: {
+            ...state[action.windowId],
+            companionAreaOpen: true,
+            sideBarPanel: action.payload.content,
+            companionWindowIds: newCompanionWindowIds.concat([action.id]),
+          },
+        };
+      }
+
+      return {
+        ...state,
+        [action.windowId]: {
+          ...state[action.windowId],
+          companionWindowIds: state[action.windowId].companionWindowIds.concat([action.id]),
+        },
+      };
     default:
       return state;
   }