diff --git a/__tests__/src/actions/window.test.js b/__tests__/src/actions/window.test.js
index 2a819fe326cef8ba2af116450aff9140d8688d56..54ea0ce078a613c0deaf1e885adfb3b61f5400e1 100644
--- a/__tests__/src/actions/window.test.js
+++ b/__tests__/src/actions/window.test.js
@@ -2,6 +2,55 @@ import * as actions from '../../../src/state/actions';
 import ActionTypes from '../../../src/state/actions/action-types';
 
 describe('window actions', () => {
+  describe('focusWindow', () => {
+    it('should return correct action object with pan=true', () => {
+      const expectedAction = {
+        type: ActionTypes.FOCUS_WINDOW,
+        windowId: 'window',
+        position: { x: -150, y: -188 },
+      };
+
+      const mockState = {
+        windows: {
+          window: { x: 50, y: 12 },
+        },
+        companionWindows: {},
+      };
+
+      const mockDispatch = jest.fn(() => ({}));
+      const mockGetState = jest.fn(() => mockState);
+      const thunk = actions.focusWindow('window', true);
+
+      thunk(mockDispatch, mockGetState);
+
+      const action = mockDispatch.mock.calls[0][0];
+      expect(action).toEqual(expectedAction);
+    });
+    it('should return correct action object with pan=false', () => {
+      const expectedAction = {
+        type: ActionTypes.FOCUS_WINDOW,
+        windowId: 'window',
+        position: {},
+      };
+
+      const mockState = {
+        windows: {
+          window: { x: 50, y: 12 },
+        },
+        companionWindows: {},
+      };
+
+      const mockDispatch = jest.fn(() => ({}));
+      const mockGetState = jest.fn(() => mockState);
+      const thunk = actions.focusWindow('window');
+
+      thunk(mockDispatch, mockGetState);
+
+      const action = mockDispatch.mock.calls[0][0];
+      expect(action).toEqual(expectedAction);
+    });
+  });
+
   describe('addWindow', () => {
     it('should create a new window with merged defaults', () => {
       const options = {
diff --git a/__tests__/src/components/WindowList.test.js b/__tests__/src/components/WindowList.test.js
index ab552b1f3e93f532f5da2f37423e711e5f4426ae..f41fe0e608920e2f4376f6c8d4afb76feeaf5d50 100644
--- a/__tests__/src/components/WindowList.test.js
+++ b/__tests__/src/components/WindowList.test.js
@@ -56,7 +56,7 @@ describe('WindowList', () => {
       ).toBe(true);
       wrapper.find('WithStyles(MenuItem)').simulate('click', {});
       expect(handleClose).toBeCalled();
-      expect(focusWindow).toBeCalledWith('xyz');
+      expect(focusWindow).toBeCalledWith('xyz', true);
     });
   });
 
diff --git a/__tests__/src/reducers/workspace.test.js b/__tests__/src/reducers/workspace.test.js
index 9873e434d0160319f421233d64e25bcfc374382f..e4d40d59434a5b6ff1f413f91f4979a5382ac2b1 100644
--- a/__tests__/src/reducers/workspace.test.js
+++ b/__tests__/src/reducers/workspace.test.js
@@ -2,12 +2,23 @@ import { workspaceReducer } from '../../../src/state/reducers/workspace';
 import ActionTypes from '../../../src/state/actions/action-types';
 
 describe('workspace reducer', () => {
+  it('should handle FOCUS_WINDOW without position coordinates', () => {
+    expect(workspaceReducer([], {
+      type: ActionTypes.FOCUS_WINDOW,
+      windowId: 'abc123',
+    })).toEqual({
+      focusedWindowId: 'abc123',
+      viewportPosition: {},
+    });
+  });
   it('should handle FOCUS_WINDOW', () => {
     expect(workspaceReducer([], {
       type: ActionTypes.FOCUS_WINDOW,
       windowId: 'abc123',
+      position: { x: 10, y: 50 },
     })).toEqual({
       focusedWindowId: 'abc123',
+      viewportPosition: { x: 10, y: 50 },
     });
   });
   it('should handle SET_WORKSPACE_FULLSCREEN', () => {
diff --git a/src/components/WindowList.js b/src/components/WindowList.js
index d82c67f27639edcae5ce8e13beb92f804bd26e17..193e3e3592c06693407291c1e0d593329bf4f2d3 100644
--- a/src/components/WindowList.js
+++ b/src/components/WindowList.js
@@ -48,7 +48,7 @@ export class WindowList extends Component {
             <MenuItem
               key={window.id}
               selected={i === 0}
-              onClick={(e) => { focusWindow(window.id); handleClose(e); }}
+              onClick={(e) => { focusWindow(window.id, true); handleClose(e); }}
             >
               <Typography variant="body1">
                 {
diff --git a/src/state/actions/window.js b/src/state/actions/window.js
index 4faa9a962bdaa62486c550ae77efba5c9438c52c..da74d8ce01990f965936daf4144cac848bef37bb 100644
--- a/src/state/actions/window.js
+++ b/src/state/actions/window.js
@@ -7,8 +7,17 @@ import ActionTypes from './action-types';
  * @param  {String} windowId
  * @memberof ActionCreators
  */
-export function focusWindow(windowId) {
-  return { type: ActionTypes.FOCUS_WINDOW, windowId };
+export function focusWindow(windowId, pan = false) {
+  return (dispatch, getState) => {
+    const { windows } = getState();
+    const { x, y } = windows[windowId];
+
+    dispatch({
+      type: ActionTypes.FOCUS_WINDOW,
+      windowId,
+      position: pan ? { x: x - 200, y: y - 200 } : {},
+    });
+  };
 }
 
 /**
diff --git a/src/state/reducers/workspace.js b/src/state/reducers/workspace.js
index 0db841dc2ac4af71b48b2c8ba1bc4f4f3e81122f..d9606abd8ca7821bd860aac9262b73f0fc0566a8 100644
--- a/src/state/reducers/workspace.js
+++ b/src/state/reducers/workspace.js
@@ -17,7 +17,14 @@ export const workspaceReducer = (
 ) => {
   switch (action.type) {
     case ActionTypes.FOCUS_WINDOW:
-      return { ...state, focusedWindowId: action.windowId };
+      return {
+        ...state,
+        focusedWindowId: action.windowId,
+        viewportPosition: {
+          ...state.viewportPosition,
+          ...action.position,
+        },
+      };
     case ActionTypes.SET_WORKSPACE_FULLSCREEN:
       return { ...state, isFullscreenEnabled: action.isFullscreenEnabled };
     case ActionTypes.TOGGLE_ZOOM_CONTROLS:
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 894cc142ca9dfb5f0431574523ce41152bbfb81c..f98a75a1529efcf006c108fa43c9f58b34f9dfd7 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -20,6 +20,14 @@
     }
   }
 
+  &-workspace {
+    transition-duration: 0.7s;
+
+    &.react-draggable-dragging {
+      transition-duration: unset;
+    }
+  }
+
   &-companion-window-header {
     flex-wrap: wrap;
   }