diff --git a/lib/template-loader.php b/lib/template-loader.php
index 82a86e7a539e3d..b534db1637b2e4 100644
--- a/lib/template-loader.php
+++ b/lib/template-loader.php
@@ -255,18 +255,7 @@ function gutenberg_find_template_post_and_parts( $template_type, $template_hiera
// See if there is a theme block template with higher priority than the resolved template post.
$higher_priority_block_template_path = null;
$higher_priority_block_template_priority = PHP_INT_MAX;
- $block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html' );
- $block_template_files = is_array( $block_template_files ) ? $block_template_files : array();
- if ( is_child_theme() ) {
- $child_block_template_files = glob( get_template_directory() . '/block-templates/*.html' );
- $child_block_template_files = is_array( $child_block_template_files ) ? $child_block_template_files : array();
- $block_template_files = array_merge( $block_template_files, $child_block_template_files );
- }
- if ( gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing-demo' ) ) {
- $demo_block_template_files = glob( dirname( __FILE__ ) . '/demo-block-templates/*.html' );
- $demo_block_template_files = is_array( $demo_block_template_files ) ? $demo_block_template_files : array();
- $block_template_files = array_merge( $block_template_files, $demo_block_template_files );
- }
+ $block_template_files = gutenberg_get_template_paths();
foreach ( $block_template_files as $path ) {
if ( ! isset( $slug_priorities[ basename( $path, '.html' ) ] ) ) {
continue;
diff --git a/lib/templates.php b/lib/templates.php
index 971398dbd4ff8c..d0c9075b8db848 100644
--- a/lib/templates.php
+++ b/lib/templates.php
@@ -5,6 +5,31 @@
* @package gutenberg
*/
+/**
+ * Returns all block template file path of the current theme and its parent theme.
+ * Includes demo block template files if demo experiment is enabled.
+ *
+ * @return array $block_template_files A list of paths to all template files.
+ */
+function gutenberg_get_template_paths() {
+ $block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html' );
+ $block_template_files = is_array( $block_template_files ) ? $block_template_files : array();
+
+ if ( is_child_theme() ) {
+ $child_block_template_files = glob( get_template_directory() . '/block-templates/*.html' );
+ $child_block_template_files = is_array( $child_block_template_files ) ? $child_block_template_files : array();
+ $block_template_files = array_merge( $block_template_files, $child_block_template_files );
+ }
+
+ if ( gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing-demo' ) ) {
+ $demo_block_template_files = glob( dirname( __FILE__ ) . '/demo-block-templates/*.html' );
+ $demo_block_template_files = is_array( $demo_block_template_files ) ? $demo_block_template_files : array();
+ $block_template_files = array_merge( $block_template_files, $demo_block_template_files );
+ }
+
+ return $block_template_files;
+}
+
/**
* Registers block editor 'wp_template' post type.
*/
@@ -177,6 +202,13 @@ function filter_rest_wp_template_collection_params( $query_params ) {
* @return array Filtered $args.
*/
function filter_rest_wp_template_query( $args, $request ) {
+ // Create auto-drafts for each theme template files.
+ $block_template_files = gutenberg_get_template_paths();
+ foreach ( $block_template_files as $path ) {
+ $template_type = basename( $path, '.html' );
+ gutenberg_find_template_post_and_parts( $template_type, array( $template_type ) );
+ }
+
if ( $request['resolved'] ) {
$template_ids = array( 0 ); // Return nothing by default (the 0 is needed for `post__in`).
$template_types = $request['slug'] ? $request['slug'] : get_template_types();
diff --git a/packages/e2e-tests/experimental-features.js b/packages/e2e-tests/experimental-features.js
index 2a270a8431b066..bc472b4896f4ff 100644
--- a/packages/e2e-tests/experimental-features.js
+++ b/packages/e2e-tests/experimental-features.js
@@ -38,13 +38,55 @@ export function useExperimentalFeatures( features ) {
afterAll( () => setExperimentalFeaturesState( features, false ) );
}
-export const openNavigation = async () => {
- const isOpen = !! ( await page.$(
- '.edit-site-navigation-toggle.is-open'
- ) );
-
- if ( ! isOpen ) {
- await page.click( '.edit-site-navigation-toggle__button' );
- await page.waitForSelector( '.edit-site-navigation-panel' );
- }
+export const navigationPanel = {
+ async open() {
+ const isOpen = !! ( await page.$(
+ '.edit-site-navigation-toggle.is-open'
+ ) );
+
+ if ( ! isOpen ) {
+ await page.click( '.edit-site-navigation-toggle__button' );
+ await page.waitForSelector( '.edit-site-navigation-panel' );
+ }
+ },
+
+ async isRoot() {
+ const isBackToDashboardButtonVisible = !! ( await page.$(
+ '.edit-site-navigation-panel .edit-site-navigation-panel__back-to-dashboard'
+ ) );
+
+ return isBackToDashboardButtonVisible;
+ },
+
+ async back() {
+ await page.click( '.components-navigation__back-button' );
+ },
+
+ async navigate( menus ) {
+ if ( ! Array.isArray( menus ) ) {
+ menus = [ menus ];
+ }
+
+ for ( const menu of menus ) {
+ ( await this.getItemByText( menu ) ).click();
+ }
+ },
+
+ async backToRoot() {
+ while ( ! ( await this.isRoot() ) ) {
+ await this.back();
+ }
+ },
+
+ async getItemByText( text ) {
+ const selector = `//div[contains(@class, "edit-site-navigation-panel")]//button[contains(., "${ text }")]`;
+ await page.waitForXPath( selector );
+ const [ item ] = await page.$x( selector );
+ return item;
+ },
+
+ async clickItemByText( text ) {
+ const item = await this.getItemByText( text );
+ await item.click();
+ },
};
diff --git a/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js b/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js
index 6804e87d8759a0..144401156a64fe 100644
--- a/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js
+++ b/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js
@@ -20,7 +20,7 @@ import { addQueryArgs } from '@wordpress/url';
*/
import {
useExperimentalFeatures,
- openNavigation,
+ navigationPanel,
} from '../../experimental-features';
const visitSiteEditor = async () => {
@@ -34,12 +34,11 @@ const visitSiteEditor = async () => {
);
};
-const getTemplateDropdownElement = async ( itemName ) => {
- await openNavigation();
- const selector = `//div[contains(@class, "edit-site-navigation-panel")]//button[contains(., "${ itemName }")]`;
- await page.waitForXPath( selector );
- const [ item ] = await page.$x( selector );
- return item;
+const clickTemplateItem = async ( menus, itemName ) => {
+ await navigationPanel.open();
+ await navigationPanel.backToRoot();
+ await navigationPanel.navigate( menus );
+ await navigationPanel.clickItemByText( itemName );
};
const createTemplatePart = async (
@@ -169,8 +168,7 @@ describe( 'Multi-entity editor states', () => {
} );
it( 'should not dirty an entity by switching to it in the template dropdown', async () => {
- const templatePartButton = await getTemplateDropdownElement( 'header' );
- await templatePartButton.click();
+ await clickTemplateItem( 'Template parts', 'header' );
// Wait for blocks to load.
await page.waitForSelector( '.wp-block' );
@@ -178,8 +176,7 @@ describe( 'Multi-entity editor states', () => {
expect( await isEntityDirty( 'front-page' ) ).toBe( false );
// Switch back and make sure it is still clean.
- const templateButton = await getTemplateDropdownElement( 'front-page' );
- await templateButton.click();
+ await clickTemplateItem( 'Templates', 'Front page' );
await page.waitForSelector( '.wp-block' );
expect( await isEntityDirty( 'header' ) ).toBe( false );
expect( await isEntityDirty( 'front-page' ) ).toBe( false );
diff --git a/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js b/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js
index af8cb346e19f83..a2b9b5ee0237ff 100644
--- a/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js
+++ b/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js
@@ -15,7 +15,7 @@ import { addQueryArgs } from '@wordpress/url';
*/
import {
useExperimentalFeatures,
- openNavigation,
+ navigationPanel,
} from '../../experimental-features';
describe( 'Multi-entity save flow', () => {
@@ -221,7 +221,6 @@ describe( 'Multi-entity save flow', () => {
describe( 'Site Editor', () => {
// Selectors - Site editor specific.
- const demoTemplateSelector = '//button[contains(., "front-page")]';
const saveSiteSelector = '.edit-site-save-button__button';
const activeSaveSiteSelector = `${ saveSiteSelector }[aria-disabled=false]`;
const disabledSaveSiteSelector = `${ saveSiteSelector }[aria-disabled=true]`;
@@ -235,11 +234,10 @@ describe( 'Multi-entity save flow', () => {
await visitAdminPage( 'admin.php', query );
// Ensure we are on 'front-page' demo template.
- await openNavigation();
- const demoTemplateButton = await page.waitForXPath(
- demoTemplateSelector
- );
- await demoTemplateButton.click();
+ await navigationPanel.open();
+ await navigationPanel.backToRoot();
+ await navigationPanel.navigate( 'Templates' );
+ await navigationPanel.clickItemByText( 'Front page' );
// Insert a new template part placeholder.
await insertBlock( 'Template Part' );
diff --git a/packages/e2e-tests/specs/experiments/template-part.test.js b/packages/e2e-tests/specs/experiments/template-part.test.js
index dfec46717a562d..c89c15766d24c0 100644
--- a/packages/e2e-tests/specs/experiments/template-part.test.js
+++ b/packages/e2e-tests/specs/experiments/template-part.test.js
@@ -15,7 +15,7 @@ import { addQueryArgs } from '@wordpress/url';
*/
import {
useExperimentalFeatures,
- openNavigation,
+ navigationPanel,
} from '../../experimental-features';
describe( 'Template Part', () => {
@@ -46,11 +46,10 @@ describe( 'Template Part', () => {
it( 'Should load customizations when in a template even if only the slug and theme attributes are set.', async () => {
// Switch to editing the header template part.
- await openNavigation();
- const switchToHeaderTemplatePartButton = await page.waitForXPath(
- '//button[contains(text(), "header")]'
- );
- await switchToHeaderTemplatePartButton.click();
+ await navigationPanel.open();
+ await navigationPanel.backToRoot();
+ await navigationPanel.navigate( 'Template parts' );
+ await navigationPanel.clickItemByText( 'header' );
// Edit it.
await insertBlock( 'Paragraph' );
@@ -64,11 +63,10 @@ describe( 'Template Part', () => {
);
// Switch back to the front page template.
- await openNavigation();
- const [ switchToFrontPageTemplateButton ] = await page.$x(
- '//button[contains(text(), "front-page")]'
- );
- await switchToFrontPageTemplateButton.click();
+ await navigationPanel.open();
+ await navigationPanel.backToRoot();
+ await navigationPanel.navigate( 'Templates' );
+ await navigationPanel.clickItemByText( 'Front page' );
// Verify that the header template part is updated.
const [ headerTemplatePart ] = await page.$x(
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/constants.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/constants.js
new file mode 100644
index 00000000000000..2b849edfc2a9e7
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/constants.js
@@ -0,0 +1,64 @@
+export const TEMPLATES_DEFAULT_DETAILS = {
+ // General
+ 'front-page': {
+ title: 'Front page',
+ description: '',
+ },
+ archive: {
+ title: 'Archive',
+ description:
+ 'Displays the content lists when no other template is found',
+ },
+ single: {
+ title: 'Single',
+ description: 'Displays the content of a single post',
+ },
+ singular: {
+ title: 'Singular',
+ description: 'Displays the content of a single page',
+ },
+ index: {
+ title: 'Default (index)',
+ description: 'Displays the content of a single page',
+ },
+ search: {
+ title: 'Search results',
+ description: '',
+ },
+ '404': {
+ title: '404',
+ description: 'Displayed when a non-existing page requested',
+ },
+
+ // Pages
+ page: {
+ title: 'Default (Page)',
+ description: 'Displays the content of a single page',
+ },
+
+ // Posts
+ home: {
+ title: 'Posts (home)',
+ description: 'Displayed on your homepage',
+ },
+ 'archive-post': {
+ title: 'Default (Post archive)',
+ description: 'Displays a list of posts',
+ },
+ 'single-post': {
+ title: 'Default (Single post)',
+ description: 'Displays the content of a single post',
+ },
+};
+
+export const TEMPLATES_GENERAL = [
+ 'front-page',
+ 'archive',
+ 'single',
+ 'singular',
+ 'index',
+ 'search',
+ '404',
+];
+
+export const TEMPLATES_POSTS = [ 'single-post', 'archive-post', 'home' ];
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js
index 36464bcab8d9ec..05fb956e66a497 100644
--- a/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js
@@ -1,11 +1,13 @@
/**
* WordPress dependencies
*/
-import { useEffect, useRef } from '@wordpress/element';
+import { useEffect, useRef, useState } from '@wordpress/element';
import {
__experimentalNavigation as Navigation,
__experimentalNavigationMenu as NavigationMenu,
+ __experimentalNavigationItem as NavigationItem,
__experimentalNavigationBackButton as NavigationBackButton,
+ createSlotFill,
} from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
@@ -13,68 +15,78 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import TemplateSwitcher from './template-switcher';
+import TemplatesMenu from './menus/templates';
+import TemplatePartsMenu from './menus/template-parts';
+
+export const {
+ Fill: NavigationPanelPreviewFill,
+ Slot: NavigationPanelPreviewSlot,
+} = createSlotFill( 'EditSiteNavigationPanelPreview' );
const NavigationPanel = () => {
+ const [ activeMenu, setActiveMenu ] = useState( 'root' );
const ref = useRef();
useEffect( () => {
ref.current.focus();
}, [ ref ] );
- const { templateId, templatePartId, templateType, page } = useSelect(
+ const { templateId, templatePartId, templateType } = useSelect(
( select ) => {
const {
getTemplateId,
getTemplatePartId,
getTemplateType,
- getPage,
} = select( 'core/edit-site' );
return {
templateId: getTemplateId(),
templatePartId: getTemplatePartId(),
templateType: getTemplateType(),
- page: getPage(),
};
},
[]
);
- const {
- setTemplate,
- addTemplate,
- removeTemplate,
- setTemplatePart,
- } = useDispatch( 'core/edit-site' );
+ const { setTemplate, setTemplatePart } = useDispatch( 'core/edit-site' );
return (
-
+ { activeMenu === 'root' && (
+
+ ) }
+
+
+
-
-
+
+
+
+
+
+
);
};
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/template-parts.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/template-parts.js
new file mode 100644
index 00000000000000..d1005478f45270
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/template-parts.js
@@ -0,0 +1,46 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useSelect } from '@wordpress/data';
+import {
+ __experimentalNavigationItem as NavigationItem,
+ __experimentalNavigationMenu as NavigationMenu,
+} from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import TemplateNavigationItems from '../template-navigation-items';
+
+export default function TemplatePartsMenu( { onActivateItem } ) {
+ const templateParts = useSelect( ( select ) => {
+ const currentTheme = select( 'core' ).getCurrentTheme()?.textdomain;
+
+ return select( 'core' ).getEntityRecords(
+ 'postType',
+ 'wp_template_part',
+ {
+ theme: currentTheme,
+ status: [ 'publish', 'auto-draft' ],
+ per_page: -1,
+ }
+ );
+ }, [] );
+
+ return (
+
+
+
+ { ! templateParts && }
+
+ );
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-all.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-all.js
new file mode 100644
index 00000000000000..7316015029bc21
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-all.js
@@ -0,0 +1,24 @@
+/**
+ * WordPress dependencies
+ */
+import { __experimentalNavigationMenu as NavigationMenu } from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import TemplateNavigationItems from '../template-navigation-items';
+
+export default function TemplatesAllMenu( { templates, onActivateItem } ) {
+ return (
+
+
+
+ );
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-pages.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-pages.js
new file mode 100644
index 00000000000000..6cd226c251c04f
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-pages.js
@@ -0,0 +1,43 @@
+/**
+ * WordPress dependencies
+ */
+import {
+ __experimentalNavigationGroup as NavigationGroup,
+ __experimentalNavigationMenu as NavigationMenu,
+} from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import TemplateNavigationItems from '../template-navigation-items';
+
+export default function TemplatesPagesMenu( { templates, onActivateItem } ) {
+ const defaultTemplate = templates?.find( ( { slug } ) => slug === 'page' );
+ const specificPageTemplates = templates?.filter( ( { slug } ) =>
+ slug.startsWith( 'page-' )
+ );
+
+ return (
+
+
+
+
+
+ { defaultTemplate && (
+
+
+
+ ) }
+
+ );
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-posts.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-posts.js
new file mode 100644
index 00000000000000..5716abda6bdc8e
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-posts.js
@@ -0,0 +1,44 @@
+/**
+ * WordPress dependencies
+ */
+import {
+ __experimentalNavigationGroup as NavigationGroup,
+ __experimentalNavigationMenu as NavigationMenu,
+} from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import TemplateNavigationItems from '../template-navigation-items';
+import { TEMPLATES_POSTS } from '../constants';
+
+export default function TemplatePostsMenu( { templates, onActivateItem } ) {
+ const generalTemplates = templates?.find( ( { slug } ) =>
+ TEMPLATES_POSTS.includes( slug )
+ );
+ const specificTemplates = templates?.filter( ( { slug } ) =>
+ slug.startsWith( 'post-' )
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates.js
new file mode 100644
index 00000000000000..471b9a4a1d2c84
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates.js
@@ -0,0 +1,60 @@
+/**
+ * WordPress dependencies
+ */
+import {
+ __experimentalNavigationItem as NavigationItem,
+ __experimentalNavigationMenu as NavigationMenu,
+} from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import TemplatesPagesMenu from './templates-pages';
+import TemplateNavigationItems from '../template-navigation-items';
+import TemplatePostsMenu from './templates-posts';
+import { TEMPLATES_GENERAL } from '../constants';
+import { useSelect } from '@wordpress/data';
+import TemplatesAllMenu from './templates-all';
+
+export default function TemplatesMenu( { onActivateItem } ) {
+ const templates = useSelect(
+ ( select ) =>
+ select( 'core' ).getEntityRecords( 'postType', 'wp_template', {
+ status: [ 'publish', 'auto-draft' ],
+ per_page: -1,
+ } ),
+ []
+ );
+
+ const generalTemplates = templates?.filter( ( { slug } ) =>
+ TEMPLATES_GENERAL.includes( slug )
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss b/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss
index 452e967387e996..ab0210884ae17c 100644
--- a/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss
@@ -17,29 +17,6 @@
.components-navigation {
height: 100%;
}
-
- .components-navigation__item {
- position: relative;
-
- .edit-site-template-switcher__label-home-icon svg path {
- color: inherit;
- }
-
- &.is-active {
- .edit-site-template-switcher__label-customized-dot {
- background: #fff;
- }
- }
- }
-
- .edit-site-template-switcher__label-home-icon {
- top: 50%;
- transform: translateY(-50%);
- }
-
- .edit-site-template-switcher__label-customized-dot {
- right: 8px;
- }
}
.edit-site-navigation-panel__back-to-dashboard.components-button.is-tertiary {
@@ -73,3 +50,26 @@
display: block;
}
}
+
+.edit-site-navigation-panel__template-item {
+ display: block;
+
+ &.is-active .edit-site-navigation-panel__template-item-description {
+ color: $gray-100;
+ }
+
+ button {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: center;
+ height: auto;
+ min-height: $button-size;
+ text-align: left;
+ }
+}
+
+.edit-site-navigation-panel__template-item-description {
+ padding-top: $grid-unit-05;
+ color: $gray-700;
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-navigation-items.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-navigation-items.js
new file mode 100644
index 00000000000000..a0456057d15bce
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-navigation-items.js
@@ -0,0 +1,86 @@
+/**
+ * WordPress dependencies
+ */
+import {
+ Button,
+ __experimentalNavigationItem as NavigationItem,
+} from '@wordpress/components';
+import { useState } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import TemplatePreview from './template-preview';
+import { NavigationPanelPreviewFill } from '.';
+import { TEMPLATES_DEFAULT_DETAILS } from './constants';
+
+export default function TemplateNavigationItems( {
+ entityType = 'wp_template',
+ templates,
+ onActivateItem,
+} ) {
+ const [ hoveredTemplate, setHoveredTemplate ] = useState();
+
+ const onMouseEnterTemplate = ( template ) => setHoveredTemplate( template );
+ const onMouseLeaveTemplate = () => setHoveredTemplate( null );
+
+ if ( ! templates ) {
+ return null;
+ }
+
+ if ( ! Array.isArray( templates ) ) {
+ templates = [ templates ];
+ }
+
+ return (
+ <>
+ { templates.map( ( template ) => {
+ const { title: defaultTitle, description: defaultDescription } =
+ TEMPLATES_DEFAULT_DETAILS[ template.slug ] ?? {};
+ const key = `${ entityType }-${ template.id }`;
+
+ let title = template?.title?.rendered ?? template.slug;
+ if ( title !== template.slug ) {
+ title = template.title.rendered;
+ } else if ( defaultTitle ) {
+ title = defaultTitle;
+ }
+
+ const description =
+ template?.excerpt?.rendered || defaultDescription;
+
+ return (
+
+ onActivateItem( template.id ) }
+ onMouseEnter={ () =>
+ onMouseEnterTemplate( template )
+ }
+ onMouseLeave={ onMouseLeaveTemplate }
+ >
+ { title }
+ { description && (
+
+ { description }
+
+ ) }
+
+
+ );
+ } ) }
+
+ { hoveredTemplate?.content?.raw && (
+
+
+
+ ) }
+ >
+ );
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-preview.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-preview.js
new file mode 100644
index 00000000000000..e27eeb7a514128
--- /dev/null
+++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-preview.js
@@ -0,0 +1,22 @@
+/**
+ * WordPress dependencies
+ */
+import { parse } from '@wordpress/blocks';
+import { BlockPreview } from '@wordpress/block-editor';
+import { useMemo } from '@wordpress/element';
+
+export default function TemplatePreview( { rawContent } ) {
+ const blocks = useMemo( () => ( rawContent ? parse( rawContent ) : [] ), [
+ rawContent,
+ ] );
+
+ if ( ! blocks || blocks.length === 0 ) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/index.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/index.js
deleted file mode 100644
index 570ce7640e4383..00000000000000
--- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/index.js
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { useSelect } from '@wordpress/data';
-import { useState } from '@wordpress/element';
-import {
- Button,
- Tooltip,
- __experimentalNavigationGroup as NavigationGroup,
- __experimentalNavigationItem as NavigationItem,
-} from '@wordpress/components';
-import { Icon, home, plus, undo } from '@wordpress/icons';
-
-/**
- * Internal dependencies
- */
-import TemplatePreview from './template-preview';
-import ThemePreview from './theme-preview';
-
-const TEMPLATE_OVERRIDES = {
- page: ( slug ) => `page-${ slug }`,
- category: ( slug ) => `category-${ slug }`,
- post: ( slug ) => `single-post-${ slug }`,
-};
-
-function TemplateNavigationItemWithIcon( {
- item,
- icon,
- iconLabel,
- homeId,
- template,
- title,
- ...props
-} ) {
- if ( ! icon && ! iconLabel && template ) {
- if ( template.id === homeId ) {
- icon = home;
- iconLabel = __( 'Home' );
- } else if ( template.status !== 'auto-draft' ) {
- icon = (
-
- );
- iconLabel = __( 'Customized' );
- }
- }
-
- return (
-
-
- { title }
- { icon && (
-
-
-
-
-
- ) }
-
-
- );
-}
-
-export default function TemplateSwitcher( {
- page,
- activeId,
- onActiveIdChange,
- onActiveTemplatePartIdChange,
- onAddTemplate,
- onRemoveTemplate,
-} ) {
- const [ hoveredTemplatePartId, setHoveredTemplatePartId ] = useState();
- const [ themePreviewVisible, setThemePreviewVisible ] = useState( false );
-
- const onMouseEnterTemplatePart = ( id ) => setHoveredTemplatePartId( id );
- const onMouseLeaveTemplatePart = () => setHoveredTemplatePartId( null );
-
- const onMouseEnterTheme = () => setThemePreviewVisible( true );
- const onMouseLeaveTheme = () => setThemePreviewVisible( false );
-
- const { currentTheme, template, templateParts, homeId } = useSelect(
- ( select ) => {
- const {
- getCurrentTheme,
- getEntityRecord,
- getEntityRecords,
- } = select( 'core' );
-
- const _template = getEntityRecord(
- 'postType',
- 'wp_template',
- activeId
- );
-
- const { getHomeTemplateId } = select( 'core/edit-site' );
-
- return {
- currentTheme: getCurrentTheme(),
- template: _template,
- templateParts: _template
- ? getEntityRecords( 'postType', 'wp_template_part', {
- resolved: true,
- template: _template.slug,
- } )
- : null,
- homeId: getHomeTemplateId(),
- };
- },
- [ activeId ]
- );
-
- const overwriteSlug =
- page &&
- TEMPLATE_OVERRIDES[ page.type ] &&
- page.slug &&
- TEMPLATE_OVERRIDES[ page.type ]( page.slug );
-
- const overwriteTemplate = () =>
- onAddTemplate( {
- slug: overwriteSlug,
- title: overwriteSlug,
- status: 'publish',
- content: template.content.raw,
- } );
- const revertToParent = () => {
- onRemoveTemplate( activeId );
- };
-
- return (
- <>
-
- onActiveIdChange( activeId ) }
- />
-
- { overwriteSlug &&
- template &&
- overwriteSlug !== template.slug && (
-
- ) }
-
- { template && overwriteSlug === template.slug && (
-
- ) }
-
-
-
- { templateParts?.map( ( templatePart ) => {
- const key = `template-part-${ templatePart.id }`;
-
- return (
-
- onActiveTemplatePartIdChange( templatePart.id )
- }
- onMouseEnter={ () =>
- onMouseEnterTemplatePart( templatePart.id )
- }
- onMouseLeave={ onMouseLeaveTemplatePart }
- />
- );
- } ) }
-
- { ( ! templateParts || templateParts.length === 0 ) && (
-
- ) }
-
-
-
-
-
-
- { hoveredTemplatePartId && (
-
- ) }
-
- { currentTheme && themePreviewVisible && (
-
- ) }
- >
- );
-}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/style.scss b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/style.scss
deleted file mode 100644
index 2e0a1fb6d1a43a..00000000000000
--- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/style.scss
+++ /dev/null
@@ -1,45 +0,0 @@
-.edit-site-template-switcher__navigation-item {
- position: relative;
-
- &.is-active {
- .edit-site-template-switcher__customized-dot {
- background: #fff;
- }
- }
-
- .edit-site-template-switcher__navigation-item-icon svg path {
- color: inherit;
- }
-}
-
-.edit-site-template-switcher__navigation-item-icon {
- width: 24px;
- height: 24px;
- position: absolute;
- right: 20px;
- top: 50%;
- transform: translateY(-50%);
-}
-
-.edit-site-template-switcher__customized-dot {
- position: absolute;
- right: 8px;
- top: 50%;
- margin-top: -4px;
- width: 8px;
- height: 8px;
- display: block;
- background: var(--wp-admin-theme-color);
- border-radius: 50%;
-}
-
-.edit-site-template-switcher__theme-preview-name {
- font-weight: 500;
- font-size: $big-font-size;
-}
-
-.edit-site-template-switcher__theme-preview-screenshot {
- margin-bottom: $grid-unit-15;
- margin-top: $grid-unit-15;
- max-width: 100%;
-}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/template-preview.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/template-preview.js
deleted file mode 100644
index 56193a6bef08e0..00000000000000
--- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/template-preview.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { parse } from '@wordpress/blocks';
-import { useSelect } from '@wordpress/data';
-import { BlockPreview } from '@wordpress/block-editor';
-import { useMemo } from '@wordpress/element';
-
-export default function TemplatePreview( { entityId } ) {
- const template = useSelect(
- ( select ) =>
- select( 'core' ).getEntityRecord(
- 'postType',
- 'wp_template_part',
- entityId
- ),
- [ entityId ]
- );
-
- const templateRawContent = template?.content?.raw || '';
- const blocks = useMemo(
- () => ( template ? parse( templateRawContent ) : [] ),
- [ templateRawContent ]
- );
-
- if ( ! blocks || blocks.length === 0 ) {
- return null;
- }
-
- return (
-
-
-
- );
-}
diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/theme-preview.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/theme-preview.js
deleted file mode 100644
index 23d6c2889dc09c..00000000000000
--- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/theme-preview.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * External dependencies
- */
-import { truncate } from 'lodash';
-
-/**
- * WordPress dependencies
- */
-import { __, sprintf } from '@wordpress/i18n';
-
-export default function ThemePreview( {
- theme: { author, description, name, screenshot, version },
-} ) {
- return (
-
-
{ ' ' }
-
- { 'v' + version }
-
-
- {
- // translators: %s: theme author name.
- sprintf( __( 'By %s' ), [ author.raw ] )
- }
-
-
-
- { truncate(
- // We can't use `description.rendered` here because we are truncating the string
- // `description.rendered` might contain HTML tags which doesn't play nicely with truncating
- // truncate function might truncate in the middle of an HTML tag so we never
- // close the HTML tag we are already in
- description.raw,
- {
- length: 120,
- separator: /\. +/,
- }
- ) }
-
-
- );
-}
diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss
index 86c502bbe7360c..2d00d96f215554 100644
--- a/packages/edit-site/src/style.scss
+++ b/packages/edit-site/src/style.scss
@@ -8,7 +8,6 @@
@import "./components/header/navigation-toggle/style.scss";
@import "./components/left-sidebar/inserter-panel/style.scss";
@import "./components/left-sidebar/navigation-panel/style.scss";
-@import "./components/left-sidebar/navigation-panel/template-switcher/style.scss";
@import "./components/notices/style.scss";
@import "./components/page-switcher/style.scss";
@import "./components/sidebar/style.scss";