diff --git a/__tests__/src/actions/workspace.test.js b/__tests__/src/actions/workspace.test.js
index 270ca53322a36720e4e99c5b3502c5196d59d9f1..28158e00ded626dfa0e7d41eadec3432d8dbac6f 100644
--- a/__tests__/src/actions/workspace.test.js
+++ b/__tests__/src/actions/workspace.test.js
@@ -13,24 +13,6 @@ describe('workspace actions', () => {
       expect(actions.updateWorkspace(options)).toEqual(expectedAction);
     });
   });
-  describe('setWorkspaceFullscreen', () => {
-    it('should return correct action type if set to true', () => {
-      const receivedAction = actions.setWorkspaceFullscreen(true);
-      const expectedAction = {
-        isFullscreenEnabled: true,
-        type: ActionTypes.SET_WORKSPACE_FULLSCREEN,
-      };
-      expect(receivedAction).toEqual(expectedAction);
-    });
-    it('should return correct action type if set to false', () => {
-      const receivedAction = actions.setWorkspaceFullscreen(false);
-      const expectedAction = {
-        isFullscreenEnabled: false,
-        type: ActionTypes.SET_WORKSPACE_FULLSCREEN,
-      };
-      expect(receivedAction).toEqual(expectedAction);
-    });
-  });
   describe('updateWorkspaceMosaicLayout', () => {
     it('should updates mosaic layout', () => {
       const options = { foo: 'bar' };
diff --git a/__tests__/src/components/AppProviders.test.js b/__tests__/src/components/AppProviders.test.js
index 020a66b960d7ef2b3f1112dbda24ebf49783a156..8f8edbed97ce7013d695d3ad007877d1cc8c18ac 100644
--- a/__tests__/src/components/AppProviders.test.js
+++ b/__tests__/src/components/AppProviders.test.js
@@ -1,7 +1,6 @@
 import React from 'react';
 import { shallow } from 'enzyme';
 import { ThemeProvider, StylesProvider } from '@material-ui/core/styles';
-import Fullscreen from 'react-full-screen';
 import { DndContext, DndProvider } from 'react-dnd';
 import { AppProviders } from '../../../src/components/AppProviders';
 import settings from '../../../src/config/settings';
@@ -14,7 +13,6 @@ function createWrapper(props) {
     <AppProviders
       language="en"
       isFullscreenEnabled={false}
-      setWorkspaceFullscreen={() => {}}
       theme={settings.theme}
       translations={{}}
       t={k => k}
@@ -28,7 +26,6 @@ describe('AppProviders', () => {
     const wrapper = createWrapper();
     expect(wrapper.find(ThemeProvider).length).toBe(1);
     expect(wrapper.find(StylesProvider).length).toBe(1);
-    expect(wrapper.find(Fullscreen).length).toBe(1);
   });
 
   it('sets up a theme based on the config passed in merged w/ MaterialUI', () => {
@@ -44,23 +41,6 @@ describe('AppProviders', () => {
     expect(wrapper.instance().i18n.t('off')).toEqual('on');
   });
 
-  it('should pass setWorkspaceFullscreen to Fullscreen.onChange', () => {
-    const mockFn = jest.fn();
-    const wrapper = createWrapper({ setWorkspaceFullscreen: mockFn });
-    expect(wrapper.find(Fullscreen).first().prop('onChange'))
-      .toBe(mockFn);
-  });
-
-  it('should pass isFullscreenEnabled to Fullscreen.enabled', () => {
-    let wrapper = createWrapper({ isFullscreenEnabled: false });
-    expect(wrapper.find(Fullscreen).first().prop('enabled'))
-      .toEqual(false);
-
-    wrapper = createWrapper({ isFullscreenEnabled: true });
-    expect(wrapper.find(Fullscreen).first().prop('enabled'))
-      .toEqual(true);
-  });
-
   describe('componentDidUpdate()', () => {
     it('changes the i18n language if the language prop has been updated', () => {
       const wrapper = createWrapper();
diff --git a/__tests__/src/components/FullScreenButton.test.js b/__tests__/src/components/FullScreenButton.test.js
index 48701a823ad8859c11f73a1b14ee6bcfcc6c8d28..cd70231645a3abe0ca64db6f29cc391a904ac97f 100644
--- a/__tests__/src/components/FullScreenButton.test.js
+++ b/__tests__/src/components/FullScreenButton.test.js
@@ -4,18 +4,21 @@ import FullscreenIcon from '@material-ui/icons/FullscreenSharp';
 import FullscreenExitIcon from '@material-ui/icons/FullscreenExitSharp';
 import MiradorMenuButton from '../../../src/containers/MiradorMenuButton';
 import { FullScreenButton } from '../../../src/components/FullScreenButton';
+import FullScreenContext from '../../../src/contexts/FullScreenContext';
 
 /** */
-function createWrapper(props) {
+function createWrapper(props, contextProps = { active: false }) {
   return shallow(
     <FullScreenButton
       classes={{}}
       className="xyz"
-      setWorkspaceFullscreen={() => {}}
-      isFullscreenEnabled={false}
       {...props}
     />,
-  );
+    {
+      wrappingComponent: FullScreenContext.Provider,
+      wrappingComponentProps: { value: { enter: () => { }, exit: () => { }, ...contextProps } },
+    },
+  ).dive();
 }
 
 describe('FullScreenButton', () => {
@@ -30,10 +33,10 @@ describe('FullScreenButton', () => {
   });
 
   describe('when not in fullscreen', () => {
-    let setWorkspaceFullscreen;
+    let enter;
     beforeAll(() => {
-      setWorkspaceFullscreen = jest.fn();
-      wrapper = createWrapper({ setWorkspaceFullscreen });
+      enter = jest.fn();
+      wrapper = createWrapper({}, { enter });
       menuButton = wrapper.find(MiradorMenuButton);
     });
 
@@ -45,17 +48,17 @@ describe('FullScreenButton', () => {
       expect(menuButton.props()['aria-label']).toEqual('workspaceFullScreen');
     });
 
-    it('triggers the setWorkspaceFullscreen prop with the appropriate boolean', () => {
+    it('triggers the handle enter with the appropriate boolean', () => {
       menuButton.props().onClick(); // Trigger the onClick prop
-      expect(setWorkspaceFullscreen).toHaveBeenCalledWith(true);
+      expect(enter).toHaveBeenCalled();
     });
   });
 
   describe('when in fullscreen', () => {
-    let setWorkspaceFullscreen;
+    let exit;
     beforeAll(() => {
-      setWorkspaceFullscreen = jest.fn();
-      wrapper = createWrapper({ isFullscreenEnabled: true, setWorkspaceFullscreen });
+      exit = jest.fn();
+      wrapper = createWrapper({}, { active: true, exit });
       menuButton = wrapper.find(MiradorMenuButton);
     });
 
@@ -67,9 +70,9 @@ describe('FullScreenButton', () => {
       expect(menuButton.props()['aria-label']).toEqual('exitFullScreen');
     });
 
-    it('triggers the setWorkspaceFullscreen prop with the appropriate boolean', () => {
+    it('triggers the handle exit with the appropriate boolean', () => {
       menuButton.props().onClick(); // Trigger the onClick prop
-      expect(setWorkspaceFullscreen).toHaveBeenCalledWith(false);
+      expect(exit).toHaveBeenCalled();
     });
   });
 });
diff --git a/package.json b/package.json
index 179a809c5decd0500a50d9119a897429a9767ddc..5926f816211613ba7adbbb87f0b836861f940766 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
     "react-dnd-html5-backend": "^10.0.2",
     "react-dnd-multi-backend": "^5.0.0",
     "react-dnd-touch-backend": "^10.0.2",
-    "react-full-screen": "^0.2.4",
+    "react-full-screen": "^1.1.1",
     "react-i18next": "^11.7.0",
     "react-image": "^4.0.1",
     "react-mosaic-component": "^4.0.1",
diff --git a/src/components/AppProviders.js b/src/components/AppProviders.js
index aeeedc34b928f6622373be9005b843b6f3755451..25b6cb13b87a9bb61179efb8cbd50e9ea82e6452 100644
--- a/src/components/AppProviders.js
+++ b/src/components/AppProviders.js
@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
-import Fullscreen from 'react-full-screen';
+import { FullScreen, useFullScreenHandle } from 'react-full-screen';
 import { I18nextProvider } from 'react-i18next';
 import { LiveAnnouncer } from 'react-aria-live';
 import {
@@ -12,6 +12,7 @@ import HTML5toTouch from 'react-dnd-multi-backend/dist/cjs/HTML5toTouch';
 import { create } from 'jss';
 import rtl from 'jss-rtl';
 import createI18nInstance from '../i18n';
+import FullScreenContext from '../contexts/FullScreenContext';
 
 /**
  * Allow applications to opt-out of (or provide their own) drag and drop context
@@ -46,6 +47,25 @@ MaybeDndProvider.propTypes = {
   ]).isRequired,
 };
 
+/**
+ * Shim to inject the full screen handle into a context
+ */
+const FullScreenShim = ({ children }) => {
+  const handle = useFullScreenHandle();
+
+  return (
+    <FullScreen handle={handle}>
+      <FullScreenContext.Provider value={handle}>
+        {children}
+      </FullScreenContext.Provider>
+    </FullScreen>
+  );
+};
+
+FullScreenShim.propTypes = {
+  children: PropTypes.node.isRequired,
+};
+
 /**
  * This component adds viewer-specific providers.
  * @prop {Object} manifests
@@ -81,8 +101,8 @@ export class AppProviders extends Component {
   /** */
   render() {
     const {
-      children, createGenerateClassNameOptions, isFullscreenEnabled,
-      setWorkspaceFullscreen, theme, translations,
+      children, createGenerateClassNameOptions,
+      theme, translations,
       dndManager,
     } = this.props;
 
@@ -93,10 +113,7 @@ export class AppProviders extends Component {
     });
 
     return (
-      <Fullscreen
-        enabled={isFullscreenEnabled}
-        onChange={setWorkspaceFullscreen}
-      >
+      <FullScreenShim>
         <I18nextProvider i18n={this.i18n}>
           <LiveAnnouncer>
             <ThemeProvider
@@ -113,7 +130,7 @@ export class AppProviders extends Component {
             </ThemeProvider>
           </LiveAnnouncer>
         </I18nextProvider>
-      </Fullscreen>
+      </FullScreenShim>
     );
   }
 }
@@ -122,9 +139,7 @@ AppProviders.propTypes = {
   children: PropTypes.node,
   createGenerateClassNameOptions: PropTypes.object, // eslint-disable-line react/forbid-prop-types
   dndManager: PropTypes.object, // eslint-disable-line react/forbid-prop-types
-  isFullscreenEnabled: PropTypes.bool,
   language: PropTypes.string.isRequired,
-  setWorkspaceFullscreen: PropTypes.func.isRequired,
   theme: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
   translations: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
 };
@@ -133,5 +148,4 @@ AppProviders.defaultProps = {
   children: null,
   createGenerateClassNameOptions: {},
   dndManager: undefined,
-  isFullscreenEnabled: false,
 };
diff --git a/src/components/FullScreenButton.js b/src/components/FullScreenButton.js
index d51a4509c0be27d07e8916b9f1498f28a2b6c24c..40361176c5536575f35d0ae51546c91369e9a25f 100644
--- a/src/components/FullScreenButton.js
+++ b/src/components/FullScreenButton.js
@@ -3,6 +3,8 @@ import FullscreenIcon from '@material-ui/icons/FullscreenSharp';
 import FullscreenExitIcon from '@material-ui/icons/FullscreenExitSharp';
 import PropTypes from 'prop-types';
 import MiradorMenuButton from '../containers/MiradorMenuButton';
+import FullScreenContext from '../contexts/FullScreenContext';
+
 /**
  */
 export class FullScreenButton extends Component {
@@ -12,29 +14,30 @@ export class FullScreenButton extends Component {
    */
   render() {
     const {
-      className, isFullscreenEnabled, setWorkspaceFullscreen, t,
+      className, t,
     } = this.props;
     return (
-      <MiradorMenuButton
-        className={className}
-        aria-label={isFullscreenEnabled ? t('exitFullScreen') : t('workspaceFullScreen')}
-        onClick={() => setWorkspaceFullscreen(!isFullscreenEnabled)}
-      >
-        {isFullscreenEnabled ? <FullscreenExitIcon /> : <FullscreenIcon />}
-      </MiradorMenuButton>
+      <FullScreenContext.Consumer>
+        { handle => (
+          <MiradorMenuButton
+            className={className}
+            aria-label={handle.active ? t('exitFullScreen') : t('workspaceFullScreen')}
+            onClick={handle.active ? handle.exit : handle.enter}
+          >
+            {handle.active ? <FullscreenExitIcon /> : <FullscreenIcon />}
+          </MiradorMenuButton>
+        )}
+      </FullScreenContext.Consumer>
     );
   }
 }
 
 FullScreenButton.propTypes = {
   className: PropTypes.string,
-  isFullscreenEnabled: PropTypes.bool,
-  setWorkspaceFullscreen: PropTypes.func.isRequired,
   t: PropTypes.func,
 };
 
 FullScreenButton.defaultProps = {
   className: undefined,
-  isFullscreenEnabled: false,
   t: key => key,
 };
diff --git a/src/containers/AppProviders.js b/src/containers/AppProviders.js
index 58c3731855565eabc6a1e0b5205beec5a0b8b086..22e8a3a06d4381880ecb305bea240a6df748ac1b 100644
--- a/src/containers/AppProviders.js
+++ b/src/containers/AppProviders.js
@@ -1,8 +1,7 @@
 import { compose } from 'redux';
 import { connect } from 'react-redux';
 import { withPlugins } from '../extend/withPlugins';
-import * as actions from '../state/actions';
-import { getConfig, getTheme, getFullScreenEnabled } from '../state/selectors';
+import { getConfig, getTheme } from '../state/selectors';
 import { AppProviders } from '../components/AppProviders';
 
 /**
@@ -13,24 +12,14 @@ import { AppProviders } from '../components/AppProviders';
 const mapStateToProps = state => (
   {
     createGenerateClassNameOptions: getConfig(state).createGenerateClassNameOptions,
-    isFullscreenEnabled: getFullScreenEnabled(state),
     language: getConfig(state).language,
     theme: getTheme(state),
     translations: getConfig(state).translations,
   }
 );
 
-/**
- * mapDispatchToProps - used to hook up connect to action creators
- * @memberof App
- * @private
- */
-const mapDispatchToProps = {
-  setWorkspaceFullscreen: actions.setWorkspaceFullscreen,
-};
-
 const enhance = compose(
-  connect(mapStateToProps, mapDispatchToProps),
+  connect(mapStateToProps),
   withPlugins('AppProviders'),
 );
 
diff --git a/src/containers/FullScreenButton.js b/src/containers/FullScreenButton.js
index cf5cf644d87b9255dc6ec5072c0c021c5218717b..529579d68411be5959abe60e461ddd24358511c8 100644
--- a/src/containers/FullScreenButton.js
+++ b/src/containers/FullScreenButton.js
@@ -2,8 +2,6 @@ import { connect } from 'react-redux';
 import { compose } from 'redux';
 import { withTranslation } from 'react-i18next';
 import { withPlugins } from '../extend/withPlugins';
-import * as actions from '../state/actions';
-import { getFullScreenEnabled } from '../state/selectors';
 import { FullScreenButton } from '../components/FullScreenButton';
 
 /**
@@ -11,16 +9,14 @@ import { FullScreenButton } from '../components/FullScreenButton';
  * @memberof FullScreenButton
  * @private
  */
-const mapStateToProps = state => ({
-  isFullscreenEnabled: getFullScreenEnabled(state),
-});
+const mapStateToProps = _state => ({});
 
 /**
  * mapDispatchToProps - used to hook up connect to action creators
  * @memberof ManifestListItem
  * @private
  */
-const mapDispatchToProps = { setWorkspaceFullscreen: actions.setWorkspaceFullscreen };
+const mapDispatchToProps = {};
 
 const enhance = compose(
   withTranslation(),
diff --git a/src/contexts/FullScreenContext.js b/src/contexts/FullScreenContext.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c0f123d0a1f16a92720df747903cfc70a897a63
--- /dev/null
+++ b/src/contexts/FullScreenContext.js
@@ -0,0 +1,5 @@
+import { createContext } from 'react';
+
+const FullScreenContext = createContext();
+
+export default FullScreenContext;
diff --git a/src/state/actions/workspace.js b/src/state/actions/workspace.js
index 0d1d8241b80441b966526e70c0e8ed0eb7f5f4b3..5500e563bc82c79bb3975f48474e99c14771f4d5 100644
--- a/src/state/actions/workspace.js
+++ b/src/state/actions/workspace.js
@@ -9,16 +9,6 @@ export function updateWorkspace(config) {
   return { config, type: ActionTypes.UPDATE_WORKSPACE };
 }
 
-/**
- * setWorkspaceFullscreen - action creator
- *
- * @param  {Boolean} isFullscreenEnabled
- * @memberof ActionCreators
- */
-export function setWorkspaceFullscreen(isFullscreenEnabled) {
-  return { isFullscreenEnabled, type: ActionTypes.SET_WORKSPACE_FULLSCREEN };
-}
-
 /**
  * toggleZoomControls - action creator
  * @param {Boolean} showZoomControls