diff --git a/__tests__/src/components/WindowCanvasNavigationControls.test.js b/__tests__/src/components/WindowCanvasNavigationControls.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..64394bd2e840e8e8692104d69ef077fddfb332dd
--- /dev/null
+++ b/__tests__/src/components/WindowCanvasNavigationControls.test.js
@@ -0,0 +1,38 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import Typography from '@material-ui/core/Typography';
+import { WindowCanvasNavigationControls } from '../../../src/components/WindowCanvasNavigationControls';
+import ViewerNavigation from '../../../src/containers/ViewerNavigation';
+import ZoomControls from '../../../src/containers/ZoomControls';
+
+/** create wrapper */
+function createWrapper(props) {
+  return shallow(
+    <WindowCanvasNavigationControls
+      canvases={[]}
+      canvasLabel="label"
+      window={{}}
+      {...props}
+    />,
+  );
+}
+
+describe('WindowCanvasNavigationControls', () => {
+  let wrapper;
+
+  it('renders properly', () => {
+    wrapper = createWrapper();
+    expect(wrapper.matchesElement(
+      <div>
+        <ZoomControls />
+        <ViewerNavigation />
+        <Typography>label</Typography>
+      </div>,
+    )).toBe(true);
+  });
+
+  it('renders nothing when visible=false', () => {
+    wrapper = createWrapper({ visible: false });
+    expect(wrapper.matchesElement(<></>)).toBe(true);
+  });
+});
diff --git a/__tests__/src/components/WindowViewer.test.js b/__tests__/src/components/WindowViewer.test.js
index f3b21fc8939a39e238cce283f33beac1157fce03..19054e8b1c3b7e7de374770791769325f9eb2125 100644
--- a/__tests__/src/components/WindowViewer.test.js
+++ b/__tests__/src/components/WindowViewer.test.js
@@ -1,11 +1,9 @@
 import React from 'react';
 import { shallow } from 'enzyme';
 import manifesto from 'manifesto.js';
-import Typography from '@material-ui/core/Typography';
 import { WindowViewer } from '../../../src/components/WindowViewer';
 import OSDViewer from '../../../src/containers/OpenSeadragonViewer';
-import ViewerNavigation from '../../../src/containers/ViewerNavigation';
-import ZoomControls from '../../../src/containers/ZoomControls';
+import WindowCanvasNavigationControls from '../../../src/containers/WindowCanvasNavigationControls';
 import fixture from '../../fixtures/version-2/019.json';
 import emptyCanvasFixture from '../../fixtures/version-2/emptyCanvas.json';
 import otherContentFixture from '../../fixtures/version-2/299843.json';
@@ -44,11 +42,7 @@ describe('WindowViewer', () => {
     expect(wrapper.matchesElement(
       <>
         <OSDViewer>
-          <div>
-            <ZoomControls />
-            <ViewerNavigation />
-            <Typography>label</Typography>
-          </div>
+          <WindowCanvasNavigationControls />
         </OSDViewer>
       </>,
     )).toBe(true);
diff --git a/src/components/WindowCanvasNavigationControls.js b/src/components/WindowCanvasNavigationControls.js
new file mode 100644
index 0000000000000000000000000000000000000000..6044dd780dd798f0f7062f6e0a66d9b6d092f776
--- /dev/null
+++ b/src/components/WindowCanvasNavigationControls.js
@@ -0,0 +1,45 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import Typography from '@material-ui/core/Typography';
+import ZoomControls from '../containers/ZoomControls';
+import ViewerNavigation from '../containers/ViewerNavigation';
+import ns from '../config/css-ns';
+
+/**
+ * Represents the viewer controls in the mirador workspace.
+ */
+export class WindowCanvasNavigationControls extends Component {
+  /** */
+  render() {
+    const {
+      canvases, canvasLabel, visible, window,
+    } = this.props;
+
+    if (!visible) return (<></>);
+
+    return (
+      <div className={ns('canvas-nav')}>
+        <ZoomControls windowId={window.id} />
+        <ViewerNavigation window={window} canvases={canvases} />
+        {
+          canvasLabel && (
+            <Typography variant="caption" className={ns('canvas-label')}>{canvasLabel}</Typography>
+          )
+        }
+      </div>
+    );
+  }
+}
+
+
+WindowCanvasNavigationControls.propTypes = {
+  canvases: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
+  window: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
+  canvasLabel: PropTypes.string,
+  visible: PropTypes.bool,
+};
+
+WindowCanvasNavigationControls.defaultProps = {
+  canvasLabel: undefined,
+  visible: true,
+};
diff --git a/src/components/WindowViewer.js b/src/components/WindowViewer.js
index 5fa7b8176a4576d8dabd903e5b5ead7d1f3cc8ea..31f81b43f0eb8cbe02f7a6530455d18dd4c5d130 100644
--- a/src/components/WindowViewer.js
+++ b/src/components/WindowViewer.js
@@ -1,12 +1,9 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
-import Typography from '@material-ui/core/Typography';
 import OSDViewer from '../containers/OpenSeadragonViewer';
-import ZoomControls from '../containers/ZoomControls';
-import ViewerNavigation from '../containers/ViewerNavigation';
+import WindowCanvasNavigationControls from '../containers/WindowCanvasNavigationControls';
 import ManifestoCanvas from '../lib/ManifestoCanvas';
 import CanvasGroupings from '../lib/CanvasGroupings';
-import ns from '../config/css-ns';
 
 /**
  * Represents a WindowViewer in the mirador workspace. Responsible for mounting
@@ -124,7 +121,7 @@ export class WindowViewer extends Component {
    * Renders things
    */
   render() {
-    const { canvasLabel, window } = this.props;
+    const { window } = this.props;
     return (
       <>
         <OSDViewer
@@ -132,15 +129,7 @@ export class WindowViewer extends Component {
           currentCanvases={this.currentCanvases()}
           windowId={window.id}
         >
-          <div className={ns('canvas-nav')}>
-            <ZoomControls windowId={window.id} />
-            <ViewerNavigation window={window} canvases={this.canvases} />
-            {
-              canvasLabel && (
-                <Typography variant="caption" className={ns('canvas-label')}>{canvasLabel}</Typography>
-              )
-            }
-          </div>
+          <WindowCanvasNavigationControls windowId={window.id} canvases={this.canvases} />
         </OSDViewer>
       </>
     );
@@ -153,9 +142,4 @@ WindowViewer.propTypes = {
   fetchInfoResponse: PropTypes.func.isRequired,
   manifest: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
   window: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
-  canvasLabel: PropTypes.string,
-};
-
-WindowViewer.defaultProps = {
-  canvasLabel: undefined,
 };
diff --git a/src/containers/WindowCanvasNavigationControls.js b/src/containers/WindowCanvasNavigationControls.js
new file mode 100644
index 0000000000000000000000000000000000000000..c3d5f03156fbe03f793755947751e2971e6a1c1f
--- /dev/null
+++ b/src/containers/WindowCanvasNavigationControls.js
@@ -0,0 +1,23 @@
+import { connect } from 'react-redux';
+import { compose } from 'redux';
+import {
+  getCanvasLabel,
+  getSelectedCanvas,
+} from '../state/selectors';
+import { WindowCanvasNavigationControls } from '../components/WindowCanvasNavigationControls';
+
+/** */
+const mapStateToProps = (state, { windowId }) => ({
+  window: state.windows[windowId],
+  canvasLabel: getCanvasLabel(
+    getSelectedCanvas(state, windowId),
+    state.windows[windowId].canvasIndex,
+  ),
+  visible: state.workspace.focusedWindowId === windowId,
+});
+
+const enhance = compose(
+  connect(mapStateToProps),
+);
+
+export default enhance(WindowCanvasNavigationControls);
diff --git a/src/containers/WindowViewer.js b/src/containers/WindowViewer.js
index a6582987d4077c5c4748c128db446178423b646c..2086ef72ed3013d786d2e03cfe70bfbbee62b8a7 100644
--- a/src/containers/WindowViewer.js
+++ b/src/containers/WindowViewer.js
@@ -1,10 +1,6 @@
 import { compose } from 'redux';
 import { connect } from 'react-redux';
 import * as actions from '../state/actions';
-import {
-  getCanvasLabel,
-  getSelectedCanvas,
-} from '../state/selectors';
 import { WindowViewer } from '../components/WindowViewer';
 
 /**
@@ -14,10 +10,6 @@ import { WindowViewer } from '../components/WindowViewer';
  */
 const mapStateToProps = (state, { window }) => (
   {
-    canvasLabel: getCanvasLabel(
-      getSelectedCanvas(state, window.id),
-      state.windows[window.id].canvasIndex,
-    ),
     infoResponses: state.infoResponses,
   }
 );