Skip to content

Commit

Permalink
Update: Implement new parent and order design. (WordPress#61918)
Browse files Browse the repository at this point in the history
Co-authored-by: jorgefilipecosta <[email protected]>
Co-authored-by: jameskoster <[email protected]>
Co-authored-by: ntsekouras <[email protected]>
Co-authored-by: jasmussen <[email protected]>
  • Loading branch information
5 people authored and carstingaxion committed Jun 4, 2024
1 parent 8e9775d commit 866bfbf
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 43 deletions.
82 changes: 79 additions & 3 deletions packages/editor/src/components/page-attributes/order.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import {
Button,
Dropdown,
Flex,
FlexBlock,
__experimentalNumberControl as NumberControl,
} from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { useState } from '@wordpress/element';
import { useState, useMemo } from '@wordpress/element';
import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import PostPanelRow from '../post-panel-row';
import PostTypeSupportCheck from '../post-type-support-check';
import { store as editorStore } from '../../store';

Expand Down Expand Up @@ -41,9 +45,10 @@ function PageAttributesOrder() {
<NumberControl
__next40pxDefaultSize
label={ __( 'Order' ) }
help={ __( 'Set the page order.' ) }
value={ value }
onChange={ setUpdatedOrder }
labelPosition="side"
hideLabelFromVision
onBlur={ () => {
setOrderInput( null );
} }
Expand All @@ -66,3 +71,74 @@ export default function PageAttributesOrderWithChecks() {
</PostTypeSupportCheck>
);
}

function PostOrderToggle( { isOpen, onClick } ) {
const order = useSelect(
( select ) =>
select( editorStore ).getEditedPostAttribute( 'menu_order' ) ?? 0,
[]
);
return (
<Button
size="compact"
className="editor-post-order__panel-toggle"
variant="tertiary"
aria-expanded={ isOpen }
// translators: %s: Current post parent.
aria-label={ sprintf( __( 'Change order: %s' ), order ) }
onClick={ onClick }
>
{ order }
</Button>
);
}

export function OrderRow() {
// 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 ]
);
return (
<PostPanelRow label={ __( 'Order' ) } ref={ setPopoverAnchor }>
<Dropdown
popoverProps={ popoverProps }
className="editor-post-order__panel-dropdown"
contentClassName="editor-post-order__panel-dialog"
focusOnMount
renderToggle={ ( { isOpen, onToggle } ) => (
<PostOrderToggle isOpen={ isOpen } onClick={ onToggle } />
) }
renderContent={ ( { onClose } ) => (
<div className="editor-post-order">
<InspectorPopoverHeader
title={ __( 'Order' ) }
onClose={ onClose }
/>
<div>
{ __(
'This attribute determines the order of pages in the Pages List block.'
) }
<p>
{ __(
'Pages with the same order value will sorted alphabetically. Negative order values are also supported.'
) }
</p>
</div>
<PageAttributesOrder />
</div>
) }
/>
</PostPanelRow>
);
}
36 changes: 10 additions & 26 deletions packages/editor/src/components/page-attributes/panel.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,38 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, PanelRow } from '@wordpress/components';

import { useSelect, useDispatch } from '@wordpress/data';
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
*/
import { store as editorStore } from '../../store';
import PageAttributesCheck from './check';
import PageAttributesOrder from './order';
import PageAttributesParent from './parent';
import { OrderRow } from './order';
import { ParentRow } from './parent';

const PANEL_NAME = 'page-attributes';

function AttributesPanel() {
const { isEnabled, isOpened, postType } = useSelect( ( select ) => {
const {
getEditedPostAttribute,
isEditorPanelEnabled,
isEditorPanelOpened,
} = select( editorStore );
const { isEnabled, postType } = useSelect( ( select ) => {
const { getEditedPostAttribute, isEditorPanelEnabled } =
select( editorStore );
const { getPostType } = select( coreStore );
return {
isEnabled: isEditorPanelEnabled( PANEL_NAME ),
isOpened: isEditorPanelOpened( PANEL_NAME ),
postType: getPostType( getEditedPostAttribute( 'type' ) ),
};
}, [] );

const { toggleEditorPanelOpened } = useDispatch( editorStore );

if ( ! isEnabled || ! postType ) {
return null;
}

return (
<PanelBody
title={ postType?.labels?.attributes ?? __( 'Page attributes' ) }
opened={ isOpened }
onToggle={ () => toggleEditorPanelOpened( PANEL_NAME ) }
>
<PageAttributesParent />
<PanelRow>
<PageAttributesOrder />
</PanelRow>
</PanelBody>
<>
<ParentRow />
<OrderRow />
</>
);
}

Expand Down
100 changes: 98 additions & 2 deletions packages/editor/src/components/page-attributes/parent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@ import removeAccents from 'remove-accents';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { ComboboxControl } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import {
Button,
Dropdown,
ComboboxControl,
ExternalLink,
} from '@wordpress/components';
import { debounce } from '@wordpress/compose';
import { useState, useMemo } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { decodeEntities } from '@wordpress/html-entities';
import { store as coreStore } from '@wordpress/core-data';
import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import PostPanelRow from '../post-panel-row';
import { buildTermsTree } from '../../utils/terms';
import { store as editorStore } from '../../store';

Expand Down Expand Up @@ -169,12 +176,101 @@ export function PageAttributesParent() {
__next40pxDefaultSize
className="editor-page-attributes__parent"
label={ __( 'Parent' ) }
help={ __( 'Choose a parent page.' ) }
value={ parentPostId }
options={ parentOptions }
onFilterValueChange={ debounce( handleKeydown, 300 ) }
onChange={ handleChange }
hideLabelFromVision
/>
);
}

function PostParentToggle( { isOpen, onClick } ) {
const parentPost = useSelect( ( select ) => {
const { getEditedPostAttribute } = select( editorStore );
const parentPostId = getEditedPostAttribute( 'parent' );
if ( ! parentPostId ) {
return null;
}
const { getEntityRecord } = select( coreStore );
const postTypeSlug = getEditedPostAttribute( 'type' );
return getEntityRecord( 'postType', postTypeSlug, parentPostId );
}, [] );
const parentTitle = useMemo(
() => ( ! parentPost ? __( 'None' ) : getTitle( parentPost ) ),
[ parentPost ]
);
return (
<Button
size="compact"
className="editor-post-parent__panel-toggle"
variant="tertiary"
aria-expanded={ isOpen }
// translators: %s: Current post parent.
aria-label={ sprintf( __( 'Change parent: %s' ), parentTitle ) }
onClick={ onClick }
>
{ parentTitle }
</Button>
);
}

export function ParentRow() {
// 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 ]
);
return (
<PostPanelRow label={ __( 'Parent' ) } ref={ setPopoverAnchor }>
<Dropdown
popoverProps={ popoverProps }
className="editor-post-parent__panel-dropdown"
contentClassName="editor-post-parent__panel-dialog"
focusOnMount
renderToggle={ ( { isOpen, onToggle } ) => (
<PostParentToggle isOpen={ isOpen } onClick={ onToggle } />
) }
renderContent={ ( { onClose } ) => (
<div className="editor-post-parent">
<InspectorPopoverHeader
title={ __( 'Parent' ) }
onClose={ onClose }
/>
<div>
{ __(
"Child pages inherit characteristics from their parent, such as URL structure. For instance, if 'Web Design' is a child of 'Services,' its URL would be mysite.com/services/web-design."
) }
<p>
{ __(
'They also show up as sub-items in the default navigation menu. '
) }
<ExternalLink
href={ __(
'https://wordpress.org/documentation/article/page-post-settings-sidebar/#page-attributes'
) }
>
{ __( 'Learn more' ) }
</ExternalLink>
</p>
</div>
<PageAttributesParent />
</div>
) }
/>
</PostPanelRow>
);
}

export default PageAttributesParent;
19 changes: 19 additions & 0 deletions packages/editor/src/components/page-attributes/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.editor-post-parent__panel,
.editor-post-order__panel {
padding-top: $grid-unit-10;
.editor-post-panel__row-control > div {
width: 100%;
}
}

.editor-post-parent__panel-dialog,
.editor-post-order__panel-dialog {
.editor-post-parent,
.editor-post-order {
margin: $grid-unit-10;
}

.components-popover__content {
min-width: 320px;
}
}
2 changes: 0 additions & 2 deletions packages/editor/src/components/sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { store as interfaceStore } from '@wordpress/interface';
/**
* Internal dependencies
*/
import PageAttributesPanel from '../page-attributes/panel';
import PatternOverridesPanel from '../pattern-overrides-panel';
import PluginDocumentSettingPanel from '../plugin-document-setting-panel';
import PluginSidebar from '../plugin-sidebar';
Expand Down Expand Up @@ -117,7 +116,6 @@ const SidebarContent = ( {
) }
<PostTransformPanel />
<PostTaxonomiesPanel />
<PageAttributesPanel />
<PatternOverridesPanel />
{ extraPanels }
</Tabs.TabPanel>
Expand Down
2 changes: 2 additions & 0 deletions packages/editor/src/components/sidebar/post-summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import PostActions from '../post-actions';
import PostAuthorPanel from '../post-author/panel';
import PostCardPanel from '../post-card-panel';
import PostContentInformation from '../post-content-information';
import PageAttributesPanel from '../page-attributes/panel';
import PostDiscussionPanel from '../post-discussion/panel';
import { PrivatePostExcerptPanel as PostExcerptPanel } from '../post-excerpt/panel';
import PostFeaturedImagePanel from '../post-featured-image/panel';
Expand Down Expand Up @@ -75,6 +76,7 @@ export default function PostSummary( { onActionPerformed } ) {
<PostAuthorPanel />
<PostTemplatePanel />
<PostDiscussionPanel />
<PageAttributesPanel />
<PostSyncStatus />
<BlogTitle />
<PostsPerPage />
Expand Down
1 change: 1 addition & 0 deletions packages/editor/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
@import "./components/inserter-sidebar/style.scss";
@import "./components/keyboard-shortcut-help-modal/style.scss";
@import "./components/list-view-sidebar/style.scss";
@import "./components/page-attributes/style.scss";
@import "./components/post-author/style.scss";
@import "./components/post-actions/style.scss";
@import "./components/post-card-panel/style.scss";
Expand Down
13 changes: 3 additions & 10 deletions test/e2e/specs/editor/plugins/custom-post-types.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,7 @@ test.describe( 'Test Custom Post Types', () => {
} )
.click();

// Open the Document -> Page Attributes panel.
const pageAttributes = page.getByRole( 'button', {
name: 'Page Attributes',
} );
const isClosed =
( await pageAttributes.getAttribute( 'aria-expanded' ) ) ===
'false';
if ( isClosed ) {
await pageAttributes.click();
}
await page.locator( '.editor-post-parent__panel-toggle' ).click();

const parentPageLocator = page.getByRole( 'combobox', {
name: 'Parent',
Expand All @@ -62,6 +53,8 @@ test.describe( 'Test Custom Post Types', () => {
await editor.publishPost();
await page.reload();

await page.locator( '.editor-post-parent__panel-toggle' ).click();

// Confirm parent page selection matches after reloading.
await expect( parentPageLocator ).toHaveValue( parentPage );
} );
Expand Down

0 comments on commit 866bfbf

Please sign in to comment.