diff --git a/package-lock.json b/package-lock.json
index 7e43c07b0654e9..4fc5de3c7e023a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11001,6 +11001,7 @@
"@wordpress/element": "file:packages/element",
"@wordpress/i18n": "file:packages/i18n",
"@wordpress/icons": "file:packages/icons",
+ "@wordpress/keycodes": "file:packages/keycodes",
"@wordpress/plugins": "file:packages/plugins",
"classnames": "^2.2.5",
"lodash": "^4.17.15"
@@ -43291,9 +43292,9 @@
"dev": true
},
"unbzip2-stream": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.1.tgz",
- "integrity": "sha512-sgDYfSDPMsA4Hr2/w7vOlrJBlwzmyakk1+hW8ObLvxSp0LA36LcL2XItGvOT3OSblohSdevMuT8FQjLsqyy4sA==",
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz",
+ "integrity": "sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg==",
"dev": true,
"requires": {
"buffer": "^5.2.1",
diff --git a/packages/e2e-tests/specs/editor/various/fullscreen-mode.test.js b/packages/e2e-tests/specs/editor/various/fullscreen-mode.test.js
index 82e6c34719755d..7f24b737c64abd 100644
--- a/packages/e2e-tests/specs/editor/various/fullscreen-mode.test.js
+++ b/packages/e2e-tests/specs/editor/various/fullscreen-mode.test.js
@@ -21,11 +21,5 @@ describe( 'Fullscreen Mode', () => {
} );
expect( isFullscreenEnabled ).toBe( true );
-
- const fullscreenCloseButton = await page.$(
- '.edit-post-fullscreen-mode-close'
- );
-
- expect( fullscreenCloseButton ).not.toBeNull();
} );
} );
diff --git a/packages/edit-post/src/components/header/fullscreen-mode-close/index.js b/packages/edit-post/src/components/header/fullscreen-mode-close/index.js
deleted file mode 100644
index 27cadc4f67b365..00000000000000
--- a/packages/edit-post/src/components/header/fullscreen-mode-close/index.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * External dependencies
- */
-import { get } from 'lodash';
-
-/**
- * WordPress dependencies
- */
-import { useSelect } from '@wordpress/data';
-import { Button } from '@wordpress/components';
-import { __ } from '@wordpress/i18n';
-import { addQueryArgs } from '@wordpress/url';
-import { wordpress } from '@wordpress/icons';
-
-function FullscreenModeClose() {
- const { isActive, postType } = useSelect( ( select ) => {
- const { getCurrentPostType } = select( 'core/editor' );
- const { isFeatureActive } = select( 'core/edit-post' );
- const { getPostType } = select( 'core' );
-
- return {
- isActive: isFeatureActive( 'fullscreenMode' ),
- postType: getPostType( getCurrentPostType() ),
- };
- }, [] );
-
- if ( ! isActive || ! postType ) {
- return null;
- }
-
- return (
-
- );
-}
-
-export default FullscreenModeClose;
diff --git a/packages/edit-post/src/components/header/fullscreen-mode-close/style.scss b/packages/edit-post/src/components/header/fullscreen-mode-close/style.scss
deleted file mode 100644
index 2997e7745387b6..00000000000000
--- a/packages/edit-post/src/components/header/fullscreen-mode-close/style.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-.edit-post-fullscreen-mode-close.has-icon {
- // Do not show the toolbar icon on small screens,
- // when Fullscreen Mode is not an option in the "More" menu.
- display: none;
-
- @include break-medium() {
- display: flex;
- align-items: center;
- align-self: stretch;
- border: none;
- background: #23282e; // WP-admin gray.
- color: $white;
- border-radius: 0;
- height: auto;
- width: $header-height;
-
- &:hover {
- background: #32373d; // WP-admin light-gray.
- }
-
- &:active {
- color: $white;
- }
-
- &:focus {
- box-shadow: inset 0 0 0 $border-width-focus $theme-color, inset 0 0 0 ($border-width-focus + 1px) $white;
- }
- }
-}
diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js
index c356909e9684fe..d8e28f31486b6d 100644
--- a/packages/edit-post/src/components/header/index.js
+++ b/packages/edit-post/src/components/header/index.js
@@ -6,12 +6,11 @@ import { Button } from '@wordpress/components';
import { PostPreviewButton, PostSavedState } from '@wordpress/editor';
import { useSelect, useDispatch } from '@wordpress/data';
import { cog } from '@wordpress/icons';
-import { PinnedItems } from '@wordpress/interface';
+import { PinnedItems, AdminMenuToggle } from '@wordpress/interface';
/**
* Internal dependencies
*/
-import FullscreenModeClose from './fullscreen-mode-close';
import HeaderToolbar from './header-toolbar';
import MoreMenu from './more-menu';
import PostPublishButtonOrToggle from './post-publish-button-or-toggle';
@@ -25,6 +24,7 @@ function Header( { onToggleInserter, isInserterOpen } ) {
isPublishSidebarOpened,
isSaving,
getBlockSelectionStart,
+ isFullscreenActive,
} = useSelect(
( select ) => ( {
shortcut: select(
@@ -40,6 +40,9 @@ function Header( { onToggleInserter, isInserterOpen } ) {
isSaving: select( 'core/edit-post' ).isSavingMetaBoxes(),
getBlockSelectionStart: select( 'core/block-editor' )
.getBlockSelectionStart,
+ isFullscreenActive: select( 'core/edit-post' ).isFeatureActive(
+ 'fullscreenMode'
+ ),
} ),
[]
);
@@ -58,7 +61,7 @@ function Header( { onToggleInserter, isInserterOpen } ) {
return (
-
+ { isFullscreenActive &&
}
-
-
-);
-
-function FullscreenModeClose() {
- const isActive = useSelect( ( select ) => {
- return select( 'core/edit-site' ).isFeatureActive( 'fullscreenMode' );
- }, [] );
-
- if ( ! isActive ) {
- return null;
- }
-
- return (
-
- );
-}
-
-export default FullscreenModeClose;
diff --git a/packages/edit-site/src/components/header/fullscreen-mode-close/style.scss b/packages/edit-site/src/components/header/fullscreen-mode-close/style.scss
deleted file mode 100644
index e8b4eb7b781ccd..00000000000000
--- a/packages/edit-site/src/components/header/fullscreen-mode-close/style.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-.edit-site-fullscreen-mode-close.has-icon {
- // Do not show the toolbar icon on small screens,
- // when Fullscreen Mode is not an option in the "More" menu.
- display: none;
-
- @include break-medium() {
- display: flex;
- align-items: center;
- align-self: stretch;
- border: none;
- background: #23282e; // WP-admin gray.
- color: $white;
- border-radius: 0;
- height: auto;
- width: $header-height;
-
- &:hover {
- background: #32373d; // WP-admin light-gray.
- }
-
- &:active {
- color: $white;
- }
-
- &:focus {
- box-shadow: inset 0 0 0 $border-width-focus $theme-color, inset 0 0 0 3px $white;
- }
- }
-}
diff --git a/packages/edit-site/src/components/header/index.js b/packages/edit-site/src/components/header/index.js
index 867dc74ed1d15e..1fc21c8440a9c9 100644
--- a/packages/edit-site/src/components/header/index.js
+++ b/packages/edit-site/src/components/header/index.js
@@ -7,13 +7,13 @@ import {
ToolSelector,
Inserter,
} from '@wordpress/block-editor';
-import { PinnedItems } from '@wordpress/interface';
+import { useSelect } from '@wordpress/data';
+import { PinnedItems, AdminMenuToggle } from '@wordpress/interface';
/**
* Internal dependencies
*/
import { useEditorContext } from '../editor';
-import FullscreenModeClose from './fullscreen-mode-close';
import MoreMenu from './more-menu';
import TemplateSwitcher from '../template-switcher';
import SaveButton from '../save-button';
@@ -49,9 +49,19 @@ export default function Header() {
} ) ),
[]
);
+
+ const { isFullscreenActive } = useSelect(
+ ( select ) => ( {
+ isFullscreenActive: select( 'core/edit-site' ).isFeatureActive(
+ 'fullscreenMode'
+ ),
+ } ),
+ []
+ );
+
return (
-
+ { isFullscreenActive &&
}
+ );
+}
+
+function useToggle( { ref } ) {
+ const [ isActive, setIsActive ] = useState( false );
+ const buttonNode = ref?.current;
+
+ const adminMenuNode = document.querySelector( '#adminmenumain' );
+
+ const toggleClassName = 'is-showing-admin-menu';
+
+ const toggleAdminMenu = () => setIsActive( ! isActive );
+ const closeAdminMenu = () => setIsActive( false );
+
+ const focusFirstAdminMenuItem = () => {
+ if ( ! buttonNode ) return;
+
+ const isButtonFocused = buttonNode.matches( ':focus' );
+ const item = adminMenuNode.querySelector( '#adminmenu > li > a' );
+
+ if ( isButtonFocused && item ) {
+ item.focus();
+ }
+ };
+
+ // Renders the open/closed UI for the admin menu
+ useEffect( () => {
+ if ( isActive ) {
+ document.body.classList.add( toggleClassName );
+ } else {
+ document.body.classList.remove( toggleClassName );
+ }
+ }, [ isActive ] );
+
+ // Handles closing the admin menu when clicking outside
+ useEffect( () => {
+ const handleOnClickOutside = ( event ) => {
+ if ( ! isActive ) return;
+
+ const { target } = event;
+
+ const didClickOutside =
+ ! adminMenuNode.contains( target ) && target !== buttonNode;
+
+ if ( didClickOutside ) {
+ closeAdminMenu();
+ }
+ };
+
+ document.body.addEventListener( 'click', handleOnClickOutside );
+
+ return () => {
+ document.body.removeEventListener( 'click', handleOnClickOutside );
+ };
+ }, [ isActive, buttonNode ] );
+
+ // Handles admin menu keyboard interactions
+ useEffect( () => {
+ const handleOnKeyDown = ( event ) => {
+ if ( ! isActive ) return;
+
+ const { keyCode } = event;
+
+ if ( keyCode === ESCAPE ) {
+ closeAdminMenu();
+ }
+
+ if ( keyCode === TAB ) {
+ focusFirstAdminMenuItem();
+ }
+ };
+
+ document.body.addEventListener( 'keydown', handleOnKeyDown );
+
+ return () => {
+ document.body.removeEventListener( 'keydown', handleOnKeyDown );
+ };
+ }, [ isActive ] );
+
+ return toggleAdminMenu;
+}
+
+export default AdminMenuToggle;
diff --git a/packages/interface/src/components/admin-menu-toggle/style.scss b/packages/interface/src/components/admin-menu-toggle/style.scss
new file mode 100644
index 00000000000000..4b9689643feeeb
--- /dev/null
+++ b/packages/interface/src/components/admin-menu-toggle/style.scss
@@ -0,0 +1,53 @@
+.interface-admin-menu-toggle.has-icon {
+ // Do not show the toolbar icon on small screens,
+ // when Fullscreen Mode is not an option in the "More" menu.
+ display: none;
+
+ @include break-medium() {
+ display: flex;
+ align-items: center;
+ align-self: stretch;
+ border: none;
+ border-radius: 0;
+ height: auto;
+ margin-right: -8px;
+ width: $header-height;
+ background: #23282e; // WP-admin gray.
+ transition: all 0.12s ease-in-out;
+
+ svg {
+ padding: 6px;
+ pointer-events: none;
+ border-radius: 2px;
+ width: 44px;
+ height: 44px;
+ fill: $white;
+ }
+
+ &:hover {
+ svg {
+ fill: rgba($white, 0.8);
+ }
+ }
+
+ &:active {
+ color: $white;
+ }
+
+ &:focus {
+ box-shadow: none;
+
+ svg {
+ box-shadow: 0 0 0 1.5px color($theme-color);
+ }
+ }
+
+ body.is-showing-admin-menu & {
+ width: 160px;
+ }
+
+ body.is-showing-admin-menu.folded & {
+ width: $header-height;
+ }
+ }
+}
diff --git a/packages/interface/src/components/fullscreen-mode/style.scss b/packages/interface/src/components/fullscreen-mode/style.scss
index 9489a9f6f96512..8146dcd02d0af5 100644
--- a/packages/interface/src/components/fullscreen-mode/style.scss
+++ b/packages/interface/src/components/fullscreen-mode/style.scss
@@ -1,19 +1,69 @@
-body.js.is-fullscreen-mode {
-
+body.is-fullscreen-mode {
@include break-medium {
// Reset the html.wp-topbar padding.
// Because this uses negative margins, we have to compensate for the height.
margin-top: -$admin-bar-height;
height: calc(100% + #{ $admin-bar-height });
- #adminmenumain,
+ // Hide the top adminbar toolbar.
#wpadminbar {
display: none;
}
+ // Layer the sidebar above the editor's top bar and
+ // setup the transition
+ #adminmenumain {
+ z-index: 1;
+ transform: translateX(-160px);
+ transition: transform 0.12s ease-in-out;
+ }
+
+ // Display the sidebar offscreen, and then transition in when needed.
+ #adminmenumain,
+ #adminmenuback {
+ position: fixed;
+ top: 60px;
+ left: 0;
+ bottom: 0;
+ }
+
+ // Hides the admin menu
+ // This prevents keyboard navigation from accessing inner links
+ #adminmenuwrap {
+ //display: none;
+ }
+
+ .interface-interface-skeleton__body,
+ .interface-interface-skeleton__footer {
+ transition: margin-left 0.12s ease-in-out;
+ }
+
#wpcontent,
#wpfooter {
margin-left: 0;
}
}
}
+
+body.is-showing-admin-menu {
+ #adminmenumain {
+ transform: translateX(0);
+ }
+
+ // Show the admin menu
+ #adminmenuwrap {
+ display: block;
+ }
+
+ .interface-interface-skeleton__body,
+ .interface-interface-skeleton__footer {
+ margin-left: 160px;
+ }
+}
+
+body.is-showing-admin-menu.folded {
+ .interface-interface-skeleton__body,
+ .interface-interface-skeleton__footer {
+ margin-left: 36px;
+ }
+}
diff --git a/packages/interface/src/components/index.js b/packages/interface/src/components/index.js
index 9071a42c0ff944..16fd863b1c1f12 100644
--- a/packages/interface/src/components/index.js
+++ b/packages/interface/src/components/index.js
@@ -2,3 +2,4 @@ export { default as ComplementaryArea } from './complementary-area';
export { default as FullscreenMode } from './fullscreen-mode';
export { default as InterfaceSkeleton } from './interface-skeleton';
export { default as PinnedItems } from './pinned-items';
+export { default as AdminMenuToggle } from './admin-menu-toggle';
diff --git a/packages/interface/src/style.scss b/packages/interface/src/style.scss
index d7f1e35e6e6616..ebb08f017ddf50 100644
--- a/packages/interface/src/style.scss
+++ b/packages/interface/src/style.scss
@@ -3,3 +3,4 @@
@import "./components/fullscreen-mode/style.scss";
@import "./components/interface-skeleton/style.scss";
@import "./components/pinned-items/style.scss";
+@import "./components/admin-menu-toggle/style.scss";