diff --git a/packages/editor/src/components/blog-title/index.js b/packages/editor/src/components/blog-title/index.js
new file mode 100644
index 00000000000000..a82498b5220f4d
--- /dev/null
+++ b/packages/editor/src/components/blog-title/index.js
@@ -0,0 +1,124 @@
+/**
+ * WordPress dependencies
+ */
+import { __, sprintf } from '@wordpress/i18n';
+import { debounce } from '@wordpress/compose';
+import { useSelect, useDispatch } from '@wordpress/data';
+import { store as coreStore } from '@wordpress/core-data';
+import { decodeEntities } from '@wordpress/html-entities';
+import {
+ Button,
+ Dropdown,
+ __experimentalInputControl as InputControl,
+} from '@wordpress/components';
+import { useState, useMemo } from '@wordpress/element';
+import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';
+
+/**
+ * Internal dependencies
+ */
+import { TEMPLATE_POST_TYPE } from '../../store/constants';
+import PostPanelRow from '../post-panel-row';
+import { store as editorStore } from '../../store';
+
+const EMPTY_OBJECT = {};
+
+export default function BlogTitle() {
+ const { editEntityRecord } = useDispatch( coreStore );
+ const { postsPageTitle, postsPageId, isTemplate, postSlug } = useSelect(
+ ( select ) => {
+ const { getEntityRecord, getEditedEntityRecord } =
+ select( coreStore );
+ const siteSettings = getEntityRecord( 'root', 'site' );
+ const _postsPageRecord = siteSettings?.page_for_posts
+ ? getEditedEntityRecord(
+ 'postType',
+ 'page',
+ siteSettings?.page_for_posts
+ )
+ : EMPTY_OBJECT;
+ const { getEditedPostAttribute, getCurrentPostType } =
+ select( editorStore );
+ return {
+ postsPageId: _postsPageRecord?.id,
+ postsPageTitle: _postsPageRecord?.title,
+ isTemplate: getCurrentPostType() === TEMPLATE_POST_TYPE,
+ postSlug: getEditedPostAttribute( 'slug' ),
+ };
+ },
+ []
+ );
+ // Use internal state instead of a ref to make sure that the component
+ // re-renders when the popover's anchor updates.
+ const [ popoverAnchor, setPopoverAnchor ] = useState( null );
+ // Memoize popoverProps to avoid returning a new object every time.
+ const popoverProps = useMemo(
+ () => ( {
+ // Anchor the popover to the middle of the entire row so that it doesn't
+ // move around when the label changes.
+ anchor: popoverAnchor,
+ placement: 'left-start',
+ offset: 36,
+ shift: true,
+ } ),
+ [ popoverAnchor ]
+ );
+
+ if (
+ ! isTemplate ||
+ ! [ 'home', 'index' ].includes( postSlug ) ||
+ ! postsPageId
+ ) {
+ return null;
+ }
+
+ const setPostsPageTitle = ( newValue ) => {
+ editEntityRecord( 'postType', 'page', postsPageId, {
+ title: newValue,
+ } );
+ };
+ const decodedTitle = decodeEntities( postsPageTitle );
+ return (
+
+ (
+
+ ) }
+ renderContent={ ( { onClose } ) => (
+ <>
+
+
+ >
+ ) }
+ />
+
+ );
+}
diff --git a/packages/editor/src/components/blog-title/style.scss b/packages/editor/src/components/blog-title/style.scss
new file mode 100644
index 00000000000000..164e82979e0b30
--- /dev/null
+++ b/packages/editor/src/components/blog-title/style.scss
@@ -0,0 +1,4 @@
+.editor-blog-title-dropdown__content .components-popover__content {
+ min-width: 320px;
+ padding: $grid-unit-20;
+}
diff --git a/packages/editor/src/components/posts-per-page/index.js b/packages/editor/src/components/posts-per-page/index.js
new file mode 100644
index 00000000000000..625aeba7bd824f
--- /dev/null
+++ b/packages/editor/src/components/posts-per-page/index.js
@@ -0,0 +1,101 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useSelect, useDispatch } from '@wordpress/data';
+import { store as coreStore } from '@wordpress/core-data';
+import {
+ Button,
+ Dropdown,
+ __experimentalNumberControl as NumberControl,
+} from '@wordpress/components';
+import { useState, useMemo } from '@wordpress/element';
+import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';
+
+/**
+ * Internal dependencies
+ */
+import { TEMPLATE_POST_TYPE } from '../../store/constants';
+import { store as editorStore } from '../../store';
+import PostPanelRow from '../post-panel-row';
+
+export default function PostsPerPage() {
+ const { editEntityRecord } = useDispatch( coreStore );
+ const { postsPerPage, isTemplate, postSlug } = useSelect( ( select ) => {
+ const { getEditedPostAttribute, getCurrentPostType } =
+ select( editorStore );
+ const { getEditedEntityRecord } = select( coreStore );
+ const siteSettings = getEditedEntityRecord( 'root', 'site' );
+ return {
+ isTemplate: getCurrentPostType() === TEMPLATE_POST_TYPE,
+ postSlug: getEditedPostAttribute( 'slug' ),
+ postsPerPage: siteSettings?.posts_per_page || 1,
+ };
+ }, [] );
+ // Use internal state instead of a ref to make sure that the component
+ // re-renders when the popover's anchor updates.
+ const [ popoverAnchor, setPopoverAnchor ] = useState( null );
+ // Memoize popoverProps to avoid returning a new object every time.
+ const popoverProps = useMemo(
+ () => ( {
+ // Anchor the popover to the middle of the entire row so that it doesn't
+ // move around when the label changes.
+ anchor: popoverAnchor,
+ placement: 'left-start',
+ offset: 36,
+ shift: true,
+ } ),
+ [ popoverAnchor ]
+ );
+
+ if ( ! isTemplate || ! [ 'home', 'index' ].includes( postSlug ) ) {
+ return null;
+ }
+ const setPostsPerPage = ( newValue ) => {
+ editEntityRecord( 'root', 'site', undefined, {
+ posts_per_page: newValue,
+ } );
+ };
+ return (
+
+ (
+
+ ) }
+ renderContent={ ( { onClose } ) => (
+ <>
+
+
+ >
+ ) }
+ />
+
+ );
+}
diff --git a/packages/editor/src/components/posts-per-page/style.scss b/packages/editor/src/components/posts-per-page/style.scss
new file mode 100644
index 00000000000000..e77e9b33206320
--- /dev/null
+++ b/packages/editor/src/components/posts-per-page/style.scss
@@ -0,0 +1,4 @@
+.editor-posts-per-page-dropdown__content .components-popover__content {
+ min-width: 320px;
+ padding: $grid-unit-20;
+}
diff --git a/packages/editor/src/components/sidebar/post-summary.js b/packages/editor/src/components/sidebar/post-summary.js
index 839d60c3b188a2..8f1fb23092a5bf 100644
--- a/packages/editor/src/components/sidebar/post-summary.js
+++ b/packages/editor/src/components/sidebar/post-summary.js
@@ -25,6 +25,9 @@ import PostSyncStatus from '../post-sync-status';
import PostTemplatePanel from '../post-template/panel';
import PostTrashPanel from '../post-trash/panel';
import PostURLPanel from '../post-url/panel';
+import BlogTitle from '../blog-title';
+import PostsPerPage from '../posts-per-page';
+import SiteDiscussion from '../site-discussion';
import { store as editorStore } from '../../store';
import {
NAVIGATION_POST_TYPE,
@@ -84,10 +87,13 @@ export default function PostSummary( { onActionPerformed } ) {
+
+
+
- { isTemplate && }
+
{ fills }
{ ! isPattern &&
! isTemplate &&
diff --git a/packages/editor/src/components/site-discussion/index.js b/packages/editor/src/components/site-discussion/index.js
new file mode 100644
index 00000000000000..e4bd60db3f8a7c
--- /dev/null
+++ b/packages/editor/src/components/site-discussion/index.js
@@ -0,0 +1,138 @@
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { useSelect, useDispatch } from '@wordpress/data';
+import { store as coreStore } from '@wordpress/core-data';
+import {
+ Button,
+ Dropdown,
+ RadioControl,
+ __experimentalVStack as VStack,
+ __experimentalText as Text,
+} from '@wordpress/components';
+import { useState, useMemo } from '@wordpress/element';
+import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';
+
+/**
+ * Internal dependencies
+ */
+import { TEMPLATE_POST_TYPE } from '../../store/constants';
+import PostPanelRow from '../post-panel-row';
+import { store as editorStore } from '../../store';
+
+const COMMENT_OPTIONS = [
+ {
+ label: (
+ <>
+ { __( 'Open' ) }
+
+ { __( 'Visitors can add new comments and replies.' ) }
+
+ >
+ ),
+ value: 'open',
+ },
+ {
+ label: (
+ <>
+ { __( 'Closed' ) }
+
+ { __( 'Visitors cannot add new comments or replies.' ) }
+
+
+ { __( 'Existing comments remain visible.' ) }
+
+ >
+ ),
+ value: '',
+ },
+];
+
+export default function SiteDiscussion() {
+ const { editEntityRecord } = useDispatch( coreStore );
+ const { allowCommentsOnNewPosts, isTemplate, postSlug } = useSelect(
+ ( select ) => {
+ const { getEditedPostAttribute, getCurrentPostType } =
+ select( editorStore );
+ const { getEditedEntityRecord } = select( coreStore );
+ const siteSettings = getEditedEntityRecord( 'root', 'site' );
+ return {
+ isTemplate: getCurrentPostType() === TEMPLATE_POST_TYPE,
+ postSlug: getEditedPostAttribute( 'slug' ),
+ allowCommentsOnNewPosts:
+ siteSettings?.default_comment_status || '',
+ };
+ },
+ []
+ );
+ // Use internal state instead of a ref to make sure that the component
+ // re-renders when the popover's anchor updates.
+ const [ popoverAnchor, setPopoverAnchor ] = useState( null );
+ // Memoize popoverProps to avoid returning a new object every time.
+ const popoverProps = useMemo(
+ () => ( {
+ // Anchor the popover to the middle of the entire row so that it doesn't
+ // move around when the label changes.
+ anchor: popoverAnchor,
+ placement: 'left-start',
+ offset: 36,
+ shift: true,
+ } ),
+ [ popoverAnchor ]
+ );
+
+ if ( ! isTemplate || ! [ 'home', 'index' ].includes( postSlug ) ) {
+ return null;
+ }
+ const setAllowCommentsOnNewPosts = ( newValue ) => {
+ editEntityRecord( 'root', 'site', undefined, {
+ default_comment_status: newValue ? 'open' : null,
+ } );
+ };
+ return (
+
+ (
+
+ ) }
+ renderContent={ ( { onClose } ) => (
+ <>
+
+
+
+ { __(
+ 'Changes will apply to new posts only. Individual posts may override these settings.'
+ ) }
+
+
+
+ >
+ ) }
+ />
+
+ );
+}
diff --git a/packages/editor/src/components/site-discussion/style.scss b/packages/editor/src/components/site-discussion/style.scss
new file mode 100644
index 00000000000000..2c54424207ea5c
--- /dev/null
+++ b/packages/editor/src/components/site-discussion/style.scss
@@ -0,0 +1,19 @@
+.editor-site-discussion-dropdown__content .components-popover__content {
+ min-width: 320px;
+ padding: $grid-unit-20;
+}
+
+.editor-site-discussion__options {
+ // TODO: it's not great to override component styles.. This might be resolved
+ // by the new radio control component.
+ .components-radio-control__option {
+ align-items: flex-start;
+ }
+
+ label {
+ .components-text {
+ display: block;
+ margin-top: $grid-unit-05;
+ }
+ }
+}
diff --git a/packages/editor/src/components/template-areas/index.js b/packages/editor/src/components/template-areas/index.js
index 25cb59bf9b2ed5..0d3bbe42d02eed 100644
--- a/packages/editor/src/components/template-areas/index.js
+++ b/packages/editor/src/components/template-areas/index.js
@@ -15,6 +15,7 @@ import { __ } from '@wordpress/i18n';
*/
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
+import { TEMPLATE_POST_TYPE } from '../../store/constants';
function TemplateAreaItem( { area, clientId } ) {
const { selectBlock, toggleBlockHighlight } =
@@ -54,13 +55,21 @@ function TemplateAreaItem( { area, clientId } ) {
}
export default function TemplateAreas() {
- const templateParts = useSelect(
- ( select ) =>
- unlock( select( editorStore ) ).getCurrentTemplateTemplateParts(),
- []
- );
+ const { isTemplate, templateParts } = useSelect( ( select ) => {
+ const _isTemplate =
+ select( editorStore ).getCurrentPostType() === TEMPLATE_POST_TYPE;
+
+ return {
+ isTemplate: _isTemplate,
+ templateParts:
+ _isTemplate &&
+ unlock(
+ select( editorStore )
+ ).getCurrentTemplateTemplateParts(),
+ };
+ }, [] );
- if ( ! templateParts.length ) {
+ if ( ! isTemplate || ! templateParts.length ) {
return null;
}
diff --git a/packages/editor/src/style.scss b/packages/editor/src/style.scss
index a28a2db3ae4a28..793d83e54c5488 100644
--- a/packages/editor/src/style.scss
+++ b/packages/editor/src/style.scss
@@ -4,6 +4,7 @@
@import "./components/block-manager/style.scss";
@import "./components/collapsible-block-toolbar/style.scss";
@import "./components/block-settings-menu/style.scss";
+@import "./components/blog-title/style.scss";
@import "./components/document-bar/style.scss";
@import "./components/document-outline/style.scss";
@import "./components/document-tools/style.scss";
@@ -39,11 +40,13 @@
@import "./components/post-title/style.scss";
@import "./components/post-url/style.scss";
@import "./components/post-visibility/style.scss";
+@import "./components/posts-per-page/style.scss";
@import "./components/post-trash/style.scss";
@import "./components/preview-dropdown/style.scss";
@import "./components/save-publish-panels/style.scss";
@import "./components/start-page-options/style.scss";
@import "./components/start-template-options/style.scss";
@import "./components/sidebar/style.scss";
+@import "./components/site-discussion/style.scss";
@import "./components/table-of-contents/style.scss";
@import "./components/template-areas/style.scss";