diff --git a/packages/dataviews/src/components/dataviews/style.scss b/packages/dataviews/src/components/dataviews/style.scss
index bd75a1ff9e2a18..a357679bef1eb9 100644
--- a/packages/dataviews/src/components/dataviews/style.scss
+++ b/packages/dataviews/src/components/dataviews/style.scss
@@ -60,6 +60,16 @@
color: var(--wp-admin-theme-color);
}
}
+
+ &.dataviews-view-grid__primary-field--clickable span,
+ > .dataviews-view-table__cell-content--clickable span {
+ color: $gray-900;
+
+ &:hover {
+ color: var(--wp-admin-theme-color);
+ }
+ @include link-reset();
+ }
}
.dataviews-view-list__primary-field--clickable,
diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js
index 60e37844b2edb1..f202664389f0ff 100644
--- a/packages/edit-site/src/components/page-patterns/fields.js
+++ b/packages/edit-site/src/components/page-patterns/fields.js
@@ -6,21 +6,15 @@ import clsx from 'clsx';
/**
* WordPress dependencies
*/
-import {
- __experimentalHStack as HStack,
- Button,
- Tooltip,
- FlexBlock,
-} from '@wordpress/components';
+import { __experimentalHStack as HStack } from '@wordpress/components';
import { __, _x } from '@wordpress/i18n';
import { useState, useMemo, useId } from '@wordpress/element';
import {
BlockPreview,
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';
-import { Icon, lockSmall } from '@wordpress/icons';
+import { Icon } from '@wordpress/icons';
import { parse } from '@wordpress/blocks';
-import { decodeEntities } from '@wordpress/html-entities';
import { privateApis as routerPrivateApis } from '@wordpress/router';
/**
@@ -112,57 +106,6 @@ export const previewField = {
enableSorting: false,
};
-function TitleField( { item } ) {
- const isUserPattern = item.type === PATTERN_TYPES.user;
- const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
- const { onClick } = useLink(
- `/${ item.type }/${
- isUserPattern || isTemplatePart ? item.id : item.name
- }?canvas=edit`
- );
- const title = decodeEntities( defaultGetTitle( item ) );
- return (
-
-
- { item.type === PATTERN_TYPES.theme ? (
- title
- ) : (
-
- ) }
-
- { item.type === PATTERN_TYPES.theme && (
-
-
-
- ) }
-
- );
-}
-
-export const titleField = {
- label: __( 'Title' ),
- id: 'title',
- getValue: ( { item } ) => item.title?.raw || item.title,
- render: TitleField,
- enableHiding: false,
-};
-
const SYNC_FILTERS = [
{
value: PATTERN_SYNC_TYPES.full,
diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js
index b6753334887573..9a4dedca098030 100644
--- a/packages/edit-site/src/components/page-patterns/index.js
+++ b/packages/edit-site/src/components/page-patterns/index.js
@@ -9,6 +9,7 @@ import { usePrevious } from '@wordpress/compose';
import { useEntityRecords } from '@wordpress/core-data';
import { privateApis as editorPrivateApis } from '@wordpress/editor';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { patternTitleField } from '@wordpress/fields';
/**
* Internal dependencies
@@ -29,13 +30,12 @@ import { useEditPostAction } from '../dataviews-actions';
import {
patternStatusField,
previewField,
- titleField,
templatePartAuthorField,
} from './fields';
const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis );
const { usePostActions } = unlock( editorPrivateApis );
-const { useLocation } = unlock( routerPrivateApis );
+const { useLocation, useHistory } = unlock( routerPrivateApis );
const EMPTY_ARRAY = [];
const defaultLayouts = {
@@ -74,6 +74,7 @@ export default function DataviewsPatterns() {
const {
query: { postType = 'wp_block', categoryId: categoryIdFromURL },
} = useLocation();
+ const history = useHistory();
const categoryId = categoryIdFromURL || PATTERN_DEFAULT_CATEGORY;
const [ view, setView ] = useState( DEFAULT_VIEW );
const previousCategoryId = usePrevious( categoryId );
@@ -105,7 +106,7 @@ export default function DataviewsPatterns() {
}, [ records ] );
const fields = useMemo( () => {
- const _fields = [ previewField, titleField ];
+ const _fields = [ previewField, patternTitleField ];
if ( postType === PATTERN_TYPES.user ) {
_fields.push( patternStatusField );
@@ -183,6 +184,21 @@ export default function DataviewsPatterns() {
data={ dataWithPermissions || EMPTY_ARRAY }
getItemId={ ( item ) => item.name ?? item.id }
isLoading={ isResolving }
+ isItemClickable={ ( item ) =>
+ item.type !== PATTERN_TYPES.theme
+ }
+ onClickItem={ ( item ) => {
+ history.navigate(
+ `/${ item.type }/${
+ [
+ PATTERN_TYPES.user,
+ TEMPLATE_PART_POST_TYPE,
+ ].includes( item.type )
+ ? item.id
+ : item.name
+ }?canvas=edit`
+ );
+ } }
view={ view }
onChangeView={ setView }
defaultLayouts={ defaultLayouts }
diff --git a/packages/edit-site/src/components/page-patterns/style.scss b/packages/edit-site/src/components/page-patterns/style.scss
index d59cce420202ee..72d53c2a721afc 100644
--- a/packages/edit-site/src/components/page-patterns/style.scss
+++ b/packages/edit-site/src/components/page-patterns/style.scss
@@ -71,34 +71,6 @@
}
}
-.edit-site-patterns__pattern-title {
- display: block;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- color: inherit;
-
- .is-link {
- text-decoration: none;
- color: $gray-200;
-
- &:hover,
- &:focus {
- color: $white;
- }
- }
-
- .edit-site-patterns__pattern-icon {
- border-radius: $grid-unit-05;
- background: var(--wp-block-synced-color);
- fill: $white;
- }
-
- .edit-site-patterns__pattern-lock-icon {
- fill: currentcolor;
- }
-}
-
.edit-site-page-patterns-dataviews {
.dataviews-view-grid__badge-fields {
.dataviews-view-grid__field-value:has(.edit-site-patterns__field-sync-status-fully) {
diff --git a/packages/edit-site/src/components/page-templates/fields.js b/packages/edit-site/src/components/page-templates/fields.js
index 35d7b9714d5be1..88c20ff27ebbce 100644
--- a/packages/edit-site/src/components/page-templates/fields.js
+++ b/packages/edit-site/src/components/page-templates/fields.js
@@ -25,7 +25,7 @@ import { useAddedBy } from './hooks';
import usePatternSettings from '../page-patterns/use-pattern-settings';
import { unlock } from '../../lock-unlock';
-const { useLink, Link } = unlock( routerPrivateApis );
+const { useLink } = unlock( routerPrivateApis );
const { useGlobalStyle } = unlock( blockEditorPrivateApis );
function PreviewField( { item } ) {
@@ -75,23 +75,6 @@ export const previewField = {
enableSorting: false,
};
-function TitleField( { item } ) {
- return (
-
- { decodeEntities( item.title?.rendered ) || __( '(no title)' ) }
-
- );
-}
-
-export const titleField = {
- label: __( 'Template' ),
- id: 'title',
- getValue: ( { item } ) => item.title?.rendered,
- render: TitleField,
- enableHiding: false,
- enableGlobalSearch: true,
-};
-
export const descriptionField = {
label: __( 'Description' ),
id: 'description',
diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js
index 828867e6f283de..934fb0be6784d7 100644
--- a/packages/edit-site/src/components/page-templates/index.js
+++ b/packages/edit-site/src/components/page-templates/index.js
@@ -7,6 +7,7 @@ import { privateApis as corePrivateApis } from '@wordpress/core-data';
import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { privateApis as editorPrivateApis } from '@wordpress/editor';
+import { templateTitleField } from '@wordpress/fields';
import { addQueryArgs } from '@wordpress/url';
/**
@@ -23,12 +24,7 @@ import {
} from '../../utils/constants';
import { unlock } from '../../lock-unlock';
import { useEditPostAction } from '../dataviews-actions';
-import {
- authorField,
- descriptionField,
- previewField,
- titleField,
-} from './fields';
+import { authorField, descriptionField, previewField } from './fields';
const { usePostActions } = unlock( editorPrivateApis );
const { useHistory, useLocation } = unlock( routerPrivateApis );
@@ -172,7 +168,7 @@ export default function PageTemplates() {
const fields = useMemo(
() => [
previewField,
- titleField,
+ templateTitleField,
descriptionField,
{
...authorField,
@@ -227,6 +223,10 @@ export default function PageTemplates() {
view={ view }
onChangeView={ onChangeView }
onChangeSelection={ onChangeSelection }
+ isItemClickable={ () => true }
+ onClickItem={ ( { id } ) => {
+ history.navigate( `/wp_template/${ id }?canvas=edit` );
+ } }
selection={ selection }
defaultLayouts={ defaultLayouts }
/>
diff --git a/packages/edit-site/src/components/post-list/style.scss b/packages/edit-site/src/components/post-list/style.scss
index 14bb11b41d4450..8ff7e31c79dd6f 100644
--- a/packages/edit-site/src/components/post-list/style.scss
+++ b/packages/edit-site/src/components/post-list/style.scss
@@ -65,42 +65,6 @@
}
}
-.edit-site-post-list__title span {
- text-overflow: ellipsis;
- overflow: hidden;
-}
-
-.dataviews-view-grid__primary-field.dataviews-view-grid__primary-field--clickable
-.edit-site-post-list__title
-span,
-.dataviews-view-table__primary-field > .dataviews-view-table__cell-content--clickable
-.edit-site-post-list__title
-span {
- text-decoration: none;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- display: block;
- flex-grow: 0;
- color: $gray-900;
-
- &:hover {
- color: var(--wp-admin-theme-color);
- }
- @include link-reset();
-}
-
-.edit-site-post-list__title-badge {
- background: $gray-100;
- color: $gray-800;
- padding: 0 $grid-unit-05;
- border-radius: $radius-small;
- font-size: 12px;
- font-weight: 400;
- flex-shrink: 0;
- line-height: $grid-unit-05 * 5;
-}
-
.edit-site-post-list__status-icon {
height: $grid-unit-30;
width: $grid-unit-30;
diff --git a/packages/editor/src/dataviews/store/private-actions.ts b/packages/editor/src/dataviews/store/private-actions.ts
index 754a02d317a385..2119b52756e964 100644
--- a/packages/editor/src/dataviews/store/private-actions.ts
+++ b/packages/editor/src/dataviews/store/private-actions.ts
@@ -4,12 +4,6 @@
import { store as coreStore } from '@wordpress/core-data';
import type { Action, Field } from '@wordpress/dataviews';
import { doAction } from '@wordpress/hooks';
-
-/**
- * Internal dependencies
- */
-import { store as editorStore } from '../../store';
-import { unlock } from '../../lock-unlock';
import type { PostType } from '@wordpress/fields';
import {
viewPost,
@@ -35,8 +29,17 @@ import {
authorField,
titleField,
templateField,
+ templateTitleField,
+ pageTitleField,
+ patternTitleField,
} from '@wordpress/fields';
+/**
+ * Internal dependencies
+ */
+import { store as editorStore } from '../../store';
+import { unlock } from '../../lock-unlock';
+
export function registerEntityAction< Item >(
kind: string,
name: string,
@@ -164,16 +167,28 @@ export const registerPostTypeSchema =
postTypeConfig.supports?.thumbnail &&
currentTheme?.theme_supports?.[ 'post-thumbnails' ] &&
featuredImageField,
- titleField,
postTypeConfig.supports?.author && authorField,
statusField,
dateField,
slugField,
postTypeConfig.supports?.[ 'page-attributes' ] && parentField,
postTypeConfig.supports?.comments && commentStatusField,
- passwordField,
templateField,
+ passwordField,
].filter( Boolean );
+ if ( postTypeConfig.supports?.title ) {
+ let _titleField;
+ if ( postType === 'page' ) {
+ _titleField = pageTitleField;
+ } else if ( postType === 'wp_template' ) {
+ _titleField = templateTitleField;
+ } else if ( postType === 'wp_block' ) {
+ _titleField = patternTitleField;
+ } else {
+ _titleField = titleField;
+ }
+ fields.push( _titleField );
+ }
registry.batch( () => {
actions.forEach( ( action ) => {
diff --git a/packages/fields/README.md b/packages/fields/README.md
index 144982361be252..9ca08991aca51f 100644
--- a/packages/fields/README.md
+++ b/packages/fields/README.md
@@ -67,6 +67,10 @@ Featured Image field for BasePost.
Order field for BasePost.
+### pageTitleField
+
+Title for the page entity.
+
### parentField
Parent field for BasePost.
@@ -75,6 +79,10 @@ Parent field for BasePost.
Password field for BasePost.
+### patternTitleField
+
+Title for the pattern entity.
+
### permanentlyDeletePost
Delete action for PostWithPermissions.
@@ -111,9 +119,13 @@ Status field for BasePost.
Template field for BasePost.
+### templateTitleField
+
+Title for the template entity.
+
### titleField
-Title field for BasePost.
+Title for the any entity with a `title` property. For patterns, pages or templates you should use the respective field because there are some differences in the rendering, labels, etc.
### trashPost
diff --git a/packages/fields/src/fields/index.ts b/packages/fields/src/fields/index.ts
index 2cdf89ee13fb02..410b0bf51a2232 100644
--- a/packages/fields/src/fields/index.ts
+++ b/packages/fields/src/fields/index.ts
@@ -1,5 +1,8 @@
export { default as slugField } from './slug';
export { default as titleField } from './title';
+export { default as pageTitleField } from './page-title';
+export { default as templateTitleField } from './template-title';
+export { default as patternTitleField } from './pattern-title';
export { default as orderField } from './order';
export { default as featuredImageField } from './featured-image';
export { default as templateField } from './template';
diff --git a/packages/fields/src/fields/page-title/index.ts b/packages/fields/src/fields/page-title/index.ts
new file mode 100644
index 00000000000000..8bbf051f2b5839
--- /dev/null
+++ b/packages/fields/src/fields/page-title/index.ts
@@ -0,0 +1,28 @@
+/**
+ * WordPress dependencies
+ */
+import type { Field } from '@wordpress/dataviews';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import type { BasePost } from '../../types';
+import { getItemTitle } from '../../actions/utils';
+import PageTitleView from './view';
+
+const pageTitleField: Field< BasePost > = {
+ type: 'text',
+ id: 'title',
+ label: __( 'Title' ),
+ placeholder: __( 'No title' ),
+ getValue: ( { item } ) => getItemTitle( item ),
+ render: PageTitleView,
+ enableHiding: false,
+ enableGlobalSearch: true,
+};
+
+/**
+ * Title for the page entity.
+ */
+export default pageTitleField;
diff --git a/packages/fields/src/fields/page-title/style.scss b/packages/fields/src/fields/page-title/style.scss
new file mode 100644
index 00000000000000..def56aa466a8a1
--- /dev/null
+++ b/packages/fields/src/fields/page-title/style.scss
@@ -0,0 +1,10 @@
+.fields-field__page-title__badge {
+ background: $gray-100;
+ color: $gray-800;
+ padding: 0 $grid-unit-05;
+ border-radius: $radius-small;
+ font-size: 12px;
+ font-weight: 400;
+ flex-shrink: 0;
+ line-height: $grid-unit-05 * 5;
+}
diff --git a/packages/fields/src/fields/page-title/view.tsx b/packages/fields/src/fields/page-title/view.tsx
new file mode 100644
index 00000000000000..0be4c16d5d29ae
--- /dev/null
+++ b/packages/fields/src/fields/page-title/view.tsx
@@ -0,0 +1,38 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useSelect } from '@wordpress/data';
+import { store as coreStore } from '@wordpress/core-data';
+import type { Settings } from '@wordpress/core-data';
+
+/**
+ * Internal dependencies
+ */
+import type { CommonPost } from '../../types';
+import { BaseTitleView } from '../title/view';
+
+export default function PageTitleView( { item }: { item: CommonPost } ) {
+ const { frontPageId, postsPageId } = useSelect( ( select ) => {
+ const { getEntityRecord } = select( coreStore );
+ const siteSettings = getEntityRecord(
+ 'root',
+ 'site'
+ ) as Partial< Settings >;
+ return {
+ frontPageId: siteSettings?.page_on_front,
+ postsPageId: siteSettings?.page_for_posts,
+ };
+ }, [] );
+ return (
+
+ { [ frontPageId, postsPageId ].includes( item.id as number ) && (
+
+ { item.id === frontPageId
+ ? __( 'Homepage' )
+ : __( 'Posts Page' ) }
+
+ ) }
+
+ );
+}
diff --git a/packages/fields/src/fields/pattern-title/index.ts b/packages/fields/src/fields/pattern-title/index.ts
new file mode 100644
index 00000000000000..a3e54eea6f28d1
--- /dev/null
+++ b/packages/fields/src/fields/pattern-title/index.ts
@@ -0,0 +1,28 @@
+/**
+ * WordPress dependencies
+ */
+import type { Field } from '@wordpress/dataviews';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import type { Pattern } from '../../types';
+import { getItemTitle } from '../../actions/utils';
+import PatternTitleView from './view';
+
+const patternTitleField: Field< Pattern > = {
+ type: 'text',
+ id: 'title',
+ label: __( 'Title' ),
+ placeholder: __( 'No title' ),
+ getValue: ( { item } ) => getItemTitle( item ),
+ render: PatternTitleView,
+ enableHiding: false,
+ enableGlobalSearch: true,
+};
+
+/**
+ * Title for the pattern entity.
+ */
+export default patternTitleField;
diff --git a/packages/fields/src/fields/pattern-title/style.scss b/packages/fields/src/fields/pattern-title/style.scss
new file mode 100644
index 00000000000000..fa4d03c850beac
--- /dev/null
+++ b/packages/fields/src/fields/pattern-title/style.scss
@@ -0,0 +1,3 @@
+.fields-field__pattern-title span:first-child {
+ flex: 1;
+}
diff --git a/packages/fields/src/fields/pattern-title/view.tsx b/packages/fields/src/fields/pattern-title/view.tsx
new file mode 100644
index 00000000000000..b59360d30e0be2
--- /dev/null
+++ b/packages/fields/src/fields/pattern-title/view.tsx
@@ -0,0 +1,32 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { Icon, lockSmall } from '@wordpress/icons';
+import { Tooltip } from '@wordpress/components';
+// @ts-ignore
+import { privateApis as patternPrivateApis } from '@wordpress/patterns';
+
+/**
+ * Internal dependencies
+ */
+import type { CommonPost } from '../../types';
+import { BaseTitleView } from '../title/view';
+import { unlock } from '../../lock-unlock';
+
+export const { PATTERN_TYPES } = unlock( patternPrivateApis );
+
+export default function PatternTitleView( { item }: { item: CommonPost } ) {
+ return (
+
+ { item.type === PATTERN_TYPES.theme && (
+
+
+
+ ) }
+
+ );
+}
diff --git a/packages/fields/src/fields/template-title/index.ts b/packages/fields/src/fields/template-title/index.ts
new file mode 100644
index 00000000000000..e0d83d6ffda8f6
--- /dev/null
+++ b/packages/fields/src/fields/template-title/index.ts
@@ -0,0 +1,28 @@
+/**
+ * WordPress dependencies
+ */
+import type { Field } from '@wordpress/dataviews';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import type { Template } from '../../types';
+import { getItemTitle } from '../../actions/utils';
+import TitleView from '../title/view';
+
+const templateTitleField: Field< Template > = {
+ type: 'text',
+ label: __( 'Template' ),
+ placeholder: __( 'No title' ),
+ id: 'title',
+ getValue: ( { item } ) => getItemTitle( item ),
+ render: TitleView,
+ enableHiding: false,
+ enableGlobalSearch: true,
+};
+
+/**
+ * Title for the template entity.
+ */
+export default templateTitleField;
diff --git a/packages/fields/src/fields/title/index.ts b/packages/fields/src/fields/title/index.ts
index 111980a1ca2b0a..b4a2399526fdd9 100644
--- a/packages/fields/src/fields/title/index.ts
+++ b/packages/fields/src/fields/title/index.ts
@@ -7,11 +7,11 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import type { BasePost } from '../../types';
+import type { CommonPost } from '../../types';
import { getItemTitle } from '../../actions/utils';
-import TitleView from './title-view';
+import TitleView from './view';
-const titleField: Field< BasePost > = {
+const titleField: Field< CommonPost > = {
type: 'text',
id: 'title',
label: __( 'Title' ),
@@ -19,9 +19,12 @@ const titleField: Field< BasePost > = {
getValue: ( { item } ) => getItemTitle( item ),
render: TitleView,
enableHiding: false,
+ enableGlobalSearch: true,
};
/**
- * Title field for BasePost.
+ * Title for the any entity with a `title` property.
+ * For patterns, pages or templates you should use the respective field
+ * because there are some differences in the rendering, labels, etc.
*/
export default titleField;
diff --git a/packages/fields/src/fields/title/style.scss b/packages/fields/src/fields/title/style.scss
new file mode 100644
index 00000000000000..5b9977dcaa398c
--- /dev/null
+++ b/packages/fields/src/fields/title/style.scss
@@ -0,0 +1,8 @@
+.fields-field__title span:first-child {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ text-decoration: none;
+ white-space: nowrap;
+ display: block;
+ flex-grow: 0;
+}
diff --git a/packages/fields/src/fields/title/title-view.tsx b/packages/fields/src/fields/title/title-view.tsx
deleted file mode 100644
index f6bf5fb1817d93..00000000000000
--- a/packages/fields/src/fields/title/title-view.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __experimentalHStack as HStack } from '@wordpress/components';
-import { decodeEntities } from '@wordpress/html-entities';
-import { __ } from '@wordpress/i18n';
-import { useSelect } from '@wordpress/data';
-import { store as coreStore } from '@wordpress/core-data';
-import type { Settings } from '@wordpress/core-data';
-
-/**
- * Internal dependencies
- */
-import type { BasePost } from '../../types';
-import { getItemTitle } from '../../actions/utils';
-
-const TitleView = ( { item }: { item: BasePost } ) => {
- const { frontPageId, postsPageId } = useSelect( ( select ) => {
- const { getEntityRecord } = select( coreStore );
- const siteSettings = getEntityRecord(
- 'root',
- 'site'
- ) as Partial< Settings >;
- return {
- frontPageId: siteSettings?.page_on_front,
- postsPageId: siteSettings?.page_for_posts,
- };
- }, [] );
-
- const renderedTitle = getItemTitle( item );
-
- let suffix;
- if ( item.id === frontPageId ) {
- suffix = (
-
- { __( 'Homepage' ) }
-
- );
- } else if ( item.id === postsPageId ) {
- suffix = (
-
- { __( 'Posts Page' ) }
-
- );
- }
-
- return (
-
-
- { decodeEntities( renderedTitle ) || __( '(no title)' ) }
-
- { suffix }
-
- );
-};
-
-export default TitleView;
diff --git a/packages/fields/src/fields/title/view.tsx b/packages/fields/src/fields/title/view.tsx
new file mode 100644
index 00000000000000..b6f39796a57f05
--- /dev/null
+++ b/packages/fields/src/fields/title/view.tsx
@@ -0,0 +1,43 @@
+/**
+ * External dependencies
+ */
+import clsx from 'clsx';
+import type { ReactNode } from 'react';
+
+/**
+ * WordPress dependencies
+ */
+import { __experimentalHStack as HStack } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import type { CommonPost } from '../../types';
+import { getItemTitle } from '../../actions/utils';
+
+export function BaseTitleView( {
+ item,
+ className,
+ children,
+}: {
+ item: CommonPost;
+ className?: string;
+ children?: ReactNode;
+} ) {
+ const renderedTitle = getItemTitle( item );
+ return (
+
+ { renderedTitle || __( '(no title)' ) }
+ { children }
+
+ );
+}
+
+export default function TitleView( { item }: { item: CommonPost } ) {
+ return ;
+}
diff --git a/packages/fields/src/style.scss b/packages/fields/src/style.scss
index 582044235aef1a..d9a571270fbb68 100644
--- a/packages/fields/src/style.scss
+++ b/packages/fields/src/style.scss
@@ -2,3 +2,6 @@
@import "./fields/slug/style.scss";
@import "./fields/featured-image/style.scss";
@import "./fields/template/style.scss";
+@import "./fields/title/style.scss";
+@import "./fields/page-title/style.scss";
+@import "./fields/pattern-title/style.scss";
diff --git a/test/e2e/specs/site-editor/browser-history.spec.js b/test/e2e/specs/site-editor/browser-history.spec.js
index a2326d10e3cc51..c3eb2ac5e3a2fa 100644
--- a/test/e2e/specs/site-editor/browser-history.spec.js
+++ b/test/e2e/specs/site-editor/browser-history.spec.js
@@ -19,7 +19,9 @@ test.describe( 'Site editor browser history', () => {
// Navigate to a single template
await page.click( 'role=button[name="Templates"]' );
- await page.getByRole( 'link', { name: 'Index' } ).click();
+ await page
+ .locator( '.fields-field__title', { hasText: 'Index' } )
+ .click();
await expect( page ).toHaveURL(
'/wp-admin/site-editor.php?p=%2Fwp_template%2Femptytheme%2F%2Findex&canvas=edit'
);
diff --git a/test/e2e/specs/site-editor/new-templates-list.spec.js b/test/e2e/specs/site-editor/new-templates-list.spec.js
index 6faa85a2659cf1..d26306a6c8e3b5 100644
--- a/test/e2e/specs/site-editor/new-templates-list.spec.js
+++ b/test/e2e/specs/site-editor/new-templates-list.spec.js
@@ -27,13 +27,7 @@ test.describe( 'Templates', () => {
page.locator( '[aria-label="Templates"]' )
).toBeVisible();
- const firstTitle = page
- .getByRole( 'region', {
- name: 'Template',
- includeHidden: true,
- } )
- .getByRole( 'link', { includeHidden: true } )
- .first();
+ const firstTitle = page.locator( '.fields-field__title' ).first();
// Descending by title.
await page.getByRole( 'button', { name: 'View options' } ).click();
@@ -54,9 +48,7 @@ test.describe( 'Templates', () => {
await admin.visitSiteEditor( { postType: 'wp_template' } );
// Global search.
await page.getByRole( 'searchbox', { name: 'Search' } ).fill( 'tag' );
- const titles = page
- .getByRole( 'region', { name: 'Template' } )
- .getByRole( 'link', { includeHidden: true } );
+ const titles = page.locator( '.fields-field__title' );
await expect( titles ).toHaveCount( 1 );
await expect( titles.first() ).toHaveText( 'Tag Archives' );
await page
diff --git a/test/e2e/specs/site-editor/template-registration.spec.js b/test/e2e/specs/site-editor/template-registration.spec.js
index 90e56645813c30..ed89c7d18bf3fb 100644
--- a/test/e2e/specs/site-editor/template-registration.spec.js
+++ b/test/e2e/specs/site-editor/template-registration.spec.js
@@ -319,7 +319,9 @@ test.describe( 'Block template registration', () => {
.getByLabel( 'Dismiss this notice' )
.getByText( `"Author: Admin" reset.` );
await page.getByPlaceholder( 'Search' ).fill( 'Author: admin' );
- await page.getByRole( 'link', { name: 'Author: Admin' } ).click();
+ await page
+ .locator( '.fields-field__title', { hasText: 'Author: Admin' } )
+ .click();
const actions = page.getByLabel( 'Actions' );
await actions.first().click();
await page.getByRole( 'menuitem', { name: 'Reset' } ).click();
diff --git a/test/performance/specs/site-editor.spec.js b/test/performance/specs/site-editor.spec.js
index e72d83fa8b3aa4..c09cfe3c67b444 100644
--- a/test/performance/specs/site-editor.spec.js
+++ b/test/performance/specs/site-editor.spec.js
@@ -237,7 +237,9 @@ test.describe( 'Site Editor Performance', () => {
}
await metrics.startTracing();
- await page.getByText( 'Single Posts', { exact: true } ).click();
+ await page
+ .getByText( 'Single Posts', { exact: true } )
+ .click( { force: true } );
await metrics.stopTracing();
// Get the durations.