diff --git a/packages/block-editor/src/components/preview-options/README.md b/packages/block-editor/src/components/preview-options/README.md
deleted file mode 100644
index 80182f18d243d..0000000000000
--- a/packages/block-editor/src/components/preview-options/README.md
+++ /dev/null
@@ -1,94 +0,0 @@
-# Preview Options
-
-The `PreviewOptions` component displays the list of different preview options available in the editor.
-
-It returns a [`DropdownMenu`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/components/src/dropdown-menu) component with these different options. The options currently available in the editor are Desktop, Mobile, Tablet and "Preview in new tab".
-
-![Preview options dropdown menu](https://make.wordpress.org/core/files/2020/09/preview-options-dropdown-menu.png)
-
-## Table of contents
-
-1. [Development guidelines](#development-guidelines)
-2. [Related components](#related-components)
-
-## Development guidelines
-
-### Usage
-
-Renders the previews options of the editor in a dropdown menu.
-
-```jsx
-import { Icon, MenuGroup } from '@wordpress/components';
-import { PostPreviewButton } from '@wordpress/editor';
-import { __experimentalPreviewOptions as PreviewOptions } from '@wordpress/block-editor';
-
-const MyPreviewOptions = () => (
- { ( { onClose } ) => (
-
-
-
- { __( 'Preview in new tab' ) }
-
- >
- }
- onPreview={ onClose }
- />
-
-
- ) }
-
-);
-```
-
-### Props
-
-#### className
-
-The CSS classes added to the component.
-
-- Type: `String`
-- Required: no
-
-#### isEnabled
-
-Wheter or not the preview options are enabled for the current post.
-And example of when the preview options are not enabled is when the current post is not savable.
-
-- Type: `boolean`
-- Required: no
-- Default: true
-
-#### deviceType
-
-The device type in the preview options. It can be either Desktop or Tablet or Mobile among others.
-
-- Type: `String`
-- Required: yes
-
-#### setDeviceType
-
-Used to set the device type that will be used to display the preview inside the editor.
-
-- Type: `func`
-- Required: yes
-
-#### children
-
-A function that returns nodes to be rendered within the dropdown.
-
-- Type: `Function`
-- Required: No
-
-## Related components
-
-Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree.
diff --git a/packages/block-editor/src/components/preview-options/index.js b/packages/block-editor/src/components/preview-options/index.js
index 91018cc980bb2..8f540c35f6455 100644
--- a/packages/block-editor/src/components/preview-options/index.js
+++ b/packages/block-editor/src/components/preview-options/index.js
@@ -1,92 +1,11 @@
-/**
- * External dependencies
- */
-import classnames from 'classnames';
-
/**
* WordPress dependencies
*/
-import { useViewportMatch } from '@wordpress/compose';
-import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';
-import { __ } from '@wordpress/i18n';
-import { check, desktop, mobile, tablet } from '@wordpress/icons';
-
-export default function PreviewOptions( {
- children,
- viewLabel,
- className,
- isEnabled = true,
- deviceType,
- setDeviceType,
- label,
- showIconLabels,
-} ) {
- const isMobile = useViewportMatch( 'medium', '<' );
- if ( isMobile ) return null;
-
- const popoverProps = {
- className: classnames(
- className,
- 'block-editor-post-preview__dropdown-content'
- ),
- placement: 'bottom-end',
- };
- const toggleProps = {
- className: 'block-editor-post-preview__button-toggle',
- disabled: ! isEnabled,
- __experimentalIsFocusable: ! isEnabled,
- children: viewLabel,
- size: 'compact',
- showTooltip: ! showIconLabels,
- };
- const menuProps = {
- 'aria-label': __( 'View options' ),
- };
-
- const deviceIcons = {
- mobile,
- tablet,
- desktop,
- };
+import deprecated from '@wordpress/deprecated';
- return (
-
- { ( renderProps ) => (
- <>
-
-
-
-
-
- { children?.( renderProps ) }
- >
- ) }
-
- );
+export default function PreviewOptions() {
+ deprecated( 'wp.blockEditor.PreviewOptions', {
+ version: '6.5',
+ } );
+ return null;
}
diff --git a/packages/block-editor/src/components/preview-options/style.scss b/packages/block-editor/src/components/preview-options/style.scss
deleted file mode 100644
index fb79926ba1dee..0000000000000
--- a/packages/block-editor/src/components/preview-options/style.scss
+++ /dev/null
@@ -1,64 +0,0 @@
-.block-editor-post-preview__dropdown {
- padding: 0;
-}
-
-.block-editor-post-preview__button-resize.block-editor-post-preview__button-resize {
- padding-left: $button-size-small + $grid-unit-10 + $grid-unit-10;
-
- &.has-icon {
- padding-left: $grid-unit-10;
- }
-}
-
-.block-editor-post-preview__dropdown-content {
- &.edit-post-post-preview-dropdown {
- .components-menu-group {
- &:first-child {
- padding-bottom: $grid-unit-10;
- }
- &:last-child {
- margin-bottom: 0;
- }
- }
- }
-
- .components-menu-group + .components-menu-group {
- padding: $grid-unit-10;
- }
-}
-
-.edit-post-header__settings,
-.edit-site-header-edit-mode__actions {
- @include break-small () {
- .editor-post-preview {
- display: none;
- }
- }
-}
-
-// Reduced UI.
-.edit-post-header.has-reduced-ui {
- @include break-small() {
- // Apply transition to first two buttons.
- .edit-post-header__settings .editor-post-save-draft,
- .edit-post-header__settings .editor-post-saved-state,
- .edit-post-header__settings .block-editor-post-preview__button-toggle {
- transition: opacity 0.1s linear;
- @include reduce-motion("transition");
- }
-
- // Zero out opacity unless hovered.
- &:not(:hover) {
- .edit-post-header__settings .editor-post-save-draft,
- .edit-post-header__settings .editor-post-saved-state,
- .edit-post-header__settings .block-editor-post-preview__button-toggle {
- opacity: 0;
- }
-
- // ... or opened.
- .edit-post-header__settings .block-editor-post-preview__button-toggle.is-opened {
- opacity: 1;
- }
- }
- }
-}
diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss
index 16de2dfdb7114..80489479724ff 100644
--- a/packages/block-editor/src/style.scss
+++ b/packages/block-editor/src/style.scss
@@ -59,7 +59,6 @@
@import "./components/block-toolbar/style.scss";
@import "./components/inserter/style.scss";
-@import "./components/preview-options/style.scss";
@import "./components/spacing-sizes-control/style.scss";
@include wordpress-admin-schemes();
diff --git a/packages/e2e-test-utils-playwright/src/editor/preview.ts b/packages/e2e-test-utils-playwright/src/editor/preview.ts
index 97d3ef1d1d660..c697ca714fe96 100644
--- a/packages/e2e-test-utils-playwright/src/editor/preview.ts
+++ b/packages/e2e-test-utils-playwright/src/editor/preview.ts
@@ -19,9 +19,7 @@ export async function openPreviewPage( this: Editor ): Promise< Page > {
const editorTopBar = this.page.locator(
'role=region[name="Editor top bar"i]'
);
- const previewButton = editorTopBar.locator(
- 'role=button[name="Preview"i]'
- );
+ const previewButton = editorTopBar.locator( 'role=button[name="View"i]' );
await previewButton.click();
diff --git a/packages/e2e-test-utils/src/preview.js b/packages/e2e-test-utils/src/preview.js
index 1d96eda176675..24c5dc69dd0e2 100644
--- a/packages/e2e-test-utils/src/preview.js
+++ b/packages/e2e-test-utils/src/preview.js
@@ -10,13 +10,13 @@ export async function openPreviewPage( editorPage = page ) {
let openTabs = await browser.pages();
const expectedTabsCount = openTabs.length + 1;
await page.waitForSelector(
- '.block-editor-post-preview__button-toggle:not([disabled])'
+ '.editor-preview-dropdown__toggle:not([disabled])'
);
- await editorPage.click( '.block-editor-post-preview__button-toggle' );
+ await editorPage.click( '.editor-preview-dropdown__toggle' );
await editorPage.waitForSelector(
- '.edit-post-header-preview__button-external'
+ '.editor-preview-dropdown__button-external'
);
- await editorPage.click( '.edit-post-header-preview__button-external' );
+ await editorPage.click( '.editor-preview-dropdown__button-external' );
// Wait for the new tab to open.
while ( openTabs.length < expectedTabsCount ) {
diff --git a/packages/edit-post/src/components/device-preview/index.js b/packages/edit-post/src/components/device-preview/index.js
deleted file mode 100644
index 9fc95b943609d..0000000000000
--- a/packages/edit-post/src/components/device-preview/index.js
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { Icon, MenuGroup } from '@wordpress/components';
-import { PostPreviewButton, store as editorStore } from '@wordpress/editor';
-import { external } from '@wordpress/icons';
-import { __ } from '@wordpress/i18n';
-import { __experimentalPreviewOptions as PreviewOptions } from '@wordpress/block-editor';
-import { useDispatch, useSelect } from '@wordpress/data';
-import { store as coreStore } from '@wordpress/core-data';
-
-/**
- * Internal dependencies
- */
-import { store as editPostStore } from '../../store';
-
-export default function DevicePreview() {
- const {
- hasActiveMetaboxes,
- isPostSaveable,
- isViewable,
- deviceType,
- showIconLabels,
- } = useSelect( ( select ) => {
- const { getEditedPostAttribute } = select( editorStore );
- const { getPostType } = select( coreStore );
- const postType = getPostType( getEditedPostAttribute( 'type' ) );
-
- return {
- hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(),
- isPostSaveable: select( editorStore ).isEditedPostSaveable(),
- isViewable: postType?.viewable ?? false,
- deviceType: select( editorStore ).getDeviceType(),
- showIconLabels:
- select( editPostStore ).isFeatureActive( 'showIconLabels' ),
- };
- }, [] );
- const { setDeviceType } = useDispatch( editorStore );
-
- return (
-
- { ( { onClose } ) =>
- isViewable && (
-
-
-
- { __( 'Preview in new tab' ) }
-
- >
- }
- onPreview={ onClose }
- />
-
-
- )
- }
-
- );
-}
diff --git a/packages/edit-post/src/components/header/index.js b/packages/edit-post/src/components/header/index.js
index b92c6c44fe49f..c86b24b4b7ccf 100644
--- a/packages/edit-post/src/components/header/index.js
+++ b/packages/edit-post/src/components/header/index.js
@@ -15,6 +15,7 @@ import {
PostPreviewButton,
store as editorStore,
DocumentBar,
+ privateApis as editorPrivateApis,
} from '@wordpress/editor';
import { useEffect, useRef, useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
@@ -36,10 +37,12 @@ import FullscreenModeClose from './fullscreen-mode-close';
import HeaderToolbar from './header-toolbar';
import MoreMenu from './more-menu';
import PostPublishButtonOrToggle from './post-publish-button-or-toggle';
-import { default as DevicePreview } from '../device-preview';
import ViewLink from '../view-link';
import MainDashboardButton from './main-dashboard-button';
import { store as editPostStore } from '../../store';
+import { unlock } from '../../lock-unlock';
+
+const { PreviewDropdown } = unlock( editorPrivateApis );
const slideY = {
hidden: { y: '-50px' },
@@ -180,8 +183,14 @@ function Header( {
showIconLabels={ showIconLabels }
/>
) }
-
-
+
+
.edit-post-header__settings > .editor-post-preview {
+ & > .edit-post-header__settings > .edit-post-header__post-preview-button {
visibility: hidden;
}
& > .edit-post-header__toolbar .edit-post-header-toolbar__inserter-toggle,
& > .edit-post-header__toolbar .edit-post-header-toolbar__document-overview-toggle,
- & > .edit-post-header__settings > .block-editor-post-preview__dropdown,
+ & > .edit-post-header__settings > .editor-preview-dropdown,
& > .edit-post-header__settings > .interface-pinned-items {
display: none;
}
diff --git a/packages/edit-site/src/components/header-edit-mode/index.js b/packages/edit-site/src/components/header-edit-mode/index.js
index 2d751be691a74..a18c7e3a3eaad 100644
--- a/packages/edit-site/src/components/header-edit-mode/index.js
+++ b/packages/edit-site/src/components/header-edit-mode/index.js
@@ -7,27 +7,26 @@ import classnames from 'classnames';
* WordPress dependencies
*/
import { useViewportMatch, useReducedMotion } from '@wordpress/compose';
-import { store as coreStore } from '@wordpress/core-data';
import {
BlockToolbar,
- __experimentalPreviewOptions as PreviewOptions,
store as blockEditorStore,
} from '@wordpress/block-editor';
-import { useSelect, useDispatch } from '@wordpress/data';
+import { useSelect } from '@wordpress/data';
import { useEffect, useRef, useState } from '@wordpress/element';
import { PinnedItems } from '@wordpress/interface';
import { __ } from '@wordpress/i18n';
-import { external, next, previous } from '@wordpress/icons';
+import { next, previous } from '@wordpress/icons';
import {
Button,
__unstableMotion as motion,
- MenuGroup,
- MenuItem,
Popover,
- VisuallyHidden,
} from '@wordpress/components';
import { store as preferencesStore } from '@wordpress/preferences';
-import { DocumentBar, store as editorStore } from '@wordpress/editor';
+import {
+ DocumentBar,
+ store as editorStore,
+ privateApis as editorPrivateApis,
+} from '@wordpress/editor';
/**
* Internal dependencies
@@ -43,14 +42,14 @@ import {
import { unlock } from '../../lock-unlock';
import { FOCUSABLE_ENTITIES } from '../../utils/constants';
+const { PreviewDropdown } = unlock( editorPrivateApis );
+
export default function HeaderEditMode( { setListViewToggleElement } ) {
const {
- deviceType,
templateType,
isDistractionFree,
blockEditorMode,
blockSelectionStart,
- homeUrl,
showIconLabels,
editorCanvasView,
hasFixedToolbar,
@@ -59,9 +58,6 @@ export default function HeaderEditMode( { setListViewToggleElement } ) {
const { getEditedPostType } = select( editSiteStore );
const { getBlockSelectionStart, __unstableGetEditorMode } =
select( blockEditorStore );
- const {
- getUnstableBase, // Site index.
- } = select( coreStore );
const { get: getPreference } = select( preferencesStore );
const { getDeviceType } = select( editorStore );
@@ -70,7 +66,6 @@ export default function HeaderEditMode( { setListViewToggleElement } ) {
templateType: getEditedPostType(),
blockEditorMode: __unstableGetEditorMode(),
blockSelectionStart: getBlockSelectionStart(),
- homeUrl: getUnstableBase()?.home,
showIconLabels: getPreference(
editSiteStore.name,
'showIconLabels'
@@ -93,7 +88,6 @@ export default function HeaderEditMode( { setListViewToggleElement } ) {
const isLargeViewport = useViewportMatch( 'medium' );
const isTopToolbar = ! isZoomOutMode && hasFixedToolbar && isLargeViewport;
const blockToolbarRef = useRef();
- const { setDeviceType } = useDispatch( editorStore );
const disableMotion = useReducedMotion();
const hasDefaultEditorCanvasView = ! useHasEditorCanvasContainer();
@@ -215,34 +209,12 @@ export default function HeaderEditMode( { setListViewToggleElement } ) {
{ 'is-zoomed-out': isZoomedOutView }
) }
>
-
- { ( { onClose } ) => (
-
-
-
- ) }
-
+ disabled={
+ isFocusMode || ! hasDefaultEditorCanvasView
+ }
+ />
) }
diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js
new file mode 100644
index 0000000000000..b7d64f2eeebc6
--- /dev/null
+++ b/packages/editor/src/components/preview-dropdown/index.js
@@ -0,0 +1,136 @@
+/**
+ * WordPress dependencies
+ */
+import { useViewportMatch } from '@wordpress/compose';
+import {
+ DropdownMenu,
+ MenuGroup,
+ MenuItem,
+ VisuallyHidden,
+ Icon,
+} from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+import { check, desktop, mobile, tablet, external } from '@wordpress/icons';
+import { useSelect, useDispatch } from '@wordpress/data';
+import { store as coreStore } from '@wordpress/core-data';
+
+/**
+ * Internal dependencies
+ */
+import { store as editorStore } from '../../store';
+import PostPreviewButton from '../post-preview-button';
+
+export default function PreviewDropdown( {
+ showIconLabels,
+ forceIsAutosaveable,
+ disabled,
+} ) {
+ const { deviceType, homeUrl, isTemplate, isViewable } = useSelect(
+ ( select ) => {
+ const { getDeviceType, getCurrentPostType } = select( editorStore );
+ const { getUnstableBase, getPostType } = select( coreStore );
+ const _currentPostType = getCurrentPostType();
+ return {
+ deviceType: getDeviceType(),
+ homeUrl: getUnstableBase()?.home,
+ isTemplate: _currentPostType === 'wp_template',
+ isViewable: getPostType( _currentPostType )?.viewable ?? false,
+ };
+ },
+ []
+ );
+ const { setDeviceType } = useDispatch( editorStore );
+ const isMobile = useViewportMatch( 'medium', '<' );
+ if ( isMobile ) return null;
+
+ const popoverProps = {
+ placement: 'bottom-end',
+ };
+ const toggleProps = {
+ className: 'editor-preview-dropdown__toggle',
+ size: 'compact',
+ showTooltip: ! showIconLabels,
+ disabled,
+ __experimentalIsFocusable: disabled,
+ };
+ const menuProps = {
+ 'aria-label': __( 'View options' ),
+ };
+
+ const deviceIcons = {
+ mobile,
+ tablet,
+ desktop,
+ };
+
+ return (
+
+ { ( { onClose } ) => (
+ <>
+
+
+
+
+
+ { isTemplate && (
+
+
+
+ ) }
+ { isViewable && (
+
+
+ { __( 'Preview in new tab' ) }
+
+ >
+ }
+ onPreview={ onClose }
+ />
+
+ ) }
+ >
+ ) }
+
+ );
+}
diff --git a/packages/editor/src/components/preview-dropdown/style.scss b/packages/editor/src/components/preview-dropdown/style.scss
new file mode 100644
index 0000000000000..43fa7cdd8ecd9
--- /dev/null
+++ b/packages/editor/src/components/preview-dropdown/style.scss
@@ -0,0 +1,5 @@
+.editor-preview-dropdown__button-external {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+}
diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js
index 046feee5b9c3f..ac5bd4324946e 100644
--- a/packages/editor/src/private-apis.js
+++ b/packages/editor/src/private-apis.js
@@ -7,6 +7,7 @@ import { lock } from './lock-unlock';
import { EntitiesSavedStatesExtensible } from './components/entities-saved-states';
import useBlockEditorSettings from './components/provider/use-block-editor-settings';
import PostPanelRow from './components/post-panel-row';
+import PreviewDropdown from './components/preview-dropdown';
export const privateApis = {};
lock( privateApis, {
@@ -14,6 +15,7 @@ lock( privateApis, {
ExperimentalEditorProvider,
EntitiesSavedStatesExtensible,
PostPanelRow,
+ PreviewDropdown,
// This is a temporary private API while we're updating the site editor to use EditorProvider.
useBlockEditorSettings,
diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss
index 01e17a1a964ab..50359984af162 100644
--- a/packages/editor/src/style.scss
+++ b/packages/editor/src/style.scss
@@ -23,5 +23,6 @@
@import "./components/post-url/style.scss";
@import "./components/post-visibility/style.scss";
@import "./components/post-trash/style.scss";
+@import "./components/preview-dropdown/style.scss";
@import "./components/table-of-contents/style.scss";
@import "./components/template-validation-notice/style.scss";
diff --git a/test/e2e/specs/editor/plugins/block-context.spec.js b/test/e2e/specs/editor/plugins/block-context.spec.js
index 1fc91debd1145..c819f29bc7383 100644
--- a/test/e2e/specs/editor/plugins/block-context.spec.js
+++ b/test/e2e/specs/editor/plugins/block-context.spec.js
@@ -64,7 +64,11 @@ test.describe( 'Block context', () => {
.fill( '123' );
await editorPage
- .getByRole( 'button', { name: 'Preview', expanded: false } )
+ .getByRole( 'button', {
+ name: 'View',
+ expanded: false,
+ exact: true,
+ } )
.click();
await editorPage
.getByRole( 'menuitem', { name: 'Preview in new tab' } )
diff --git a/test/e2e/specs/editor/various/new-post.spec.js b/test/e2e/specs/editor/various/new-post.spec.js
index cc0243eb8e631..b3591db1ec50b 100644
--- a/test/e2e/specs/editor/various/new-post.spec.js
+++ b/test/e2e/specs/editor/various/new-post.spec.js
@@ -32,9 +32,9 @@ test.describe( 'new editor state', () => {
await expect( title ).toBeEditable();
await expect( title ).toHaveText( '' );
- // Should display the Preview button.
+ // Should display the View button.
await expect(
- page.locator( 'role=button[name="Preview"i]' )
+ page.locator( 'role=button[name="View"i]' )
).toBeVisible();
// Should display the Post Formats UI.
diff --git a/test/e2e/specs/editor/various/preview.spec.js b/test/e2e/specs/editor/various/preview.spec.js
index 0666de1405fae..0657a45567baf 100644
--- a/test/e2e/specs/editor/various/preview.spec.js
+++ b/test/e2e/specs/editor/various/preview.spec.js
@@ -22,11 +22,6 @@ test.describe( 'Preview', () => {
} ) => {
const editorPage = page;
- // Disabled until content present.
- await expect(
- editorPage.locator( 'role=button[name="Preview"i]' )
- ).toBeDisabled();
-
await editor.canvas
.locator( 'role=textbox[name="Add title"i]' )
.type( 'Hello World' );
@@ -301,7 +296,7 @@ test.describe( 'Preview with private custom post type', () => {
} );
// Open the view menu.
- await page.click( 'role=button[name="Preview"i]' );
+ await page.click( 'role=button[name="View"i]' );
await expect(
page.locator( 'role=menuitem[name="Preview in new tab"i]' )
@@ -316,7 +311,7 @@ class PreviewUtils {
async waitForPreviewNavigation( previewPage ) {
const previewToggle = this.page.locator(
- 'role=button[name="Preview"i][expanded=false]'
+ 'role=button[name="View"i][expanded=false]'
);
const isDropdownClosed = await previewToggle.isVisible();
if ( isDropdownClosed ) {