Skip to content

Commit

Permalink
Update: Implement the new discussion panel design. (#61357)
Browse files Browse the repository at this point in the history
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>
  • Loading branch information
4 people authored May 14, 2024
1 parent 8d7c8fd commit ef6a1ea
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 45 deletions.
56 changes: 47 additions & 9 deletions packages/editor/src/components/post-comments/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,46 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { CheckboxControl } from '@wordpress/components';
import {
RadioControl,
__experimentalText as Text,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { store as editorStore } from '../../store';

const COMMENT_OPTIONS = [
{
label: (
<>
{ __( 'Open' ) }
<Text variant="muted" size={ 12 }>
{ __( 'Visitors can add new comments and replies.' ) }
</Text>
</>
),
value: 'open',
},
{
label: (
<>
{ __( 'Closed' ) }
<Text variant="muted" size={ 12 }>
{ __( 'Visitors cannot add new comments or replies.' ) }
</Text>
<Text variant="muted" size={ 12 }>
{ __( 'Existing comments remain visible.' ) }
</Text>
</>
),
value: 'closed',
},
];

function PostComments() {
const commentStatus = useSelect(
( select ) =>
Expand All @@ -18,18 +50,24 @@ function PostComments() {
[]
);
const { editPost } = useDispatch( editorStore );
const onToggleComments = () =>
const handleStatus = ( newCommentStatus ) =>
editPost( {
comment_status: commentStatus === 'open' ? 'closed' : 'open',
comment_status: newCommentStatus,
} );

return (
<CheckboxControl
__nextHasNoMarginBottom
label={ __( 'Allow comments' ) }
checked={ commentStatus === 'open' }
onChange={ onToggleComments }
/>
<form>
<VStack spacing={ 4 }>
<RadioControl
className="editor-change-status__options"
hideLabelFromVision
label={ __( 'Comment status' ) }
options={ COMMENT_OPTIONS }
onChange={ handleStatus }
selected={ commentStatus }
/>
</VStack>
</form>
);
}

Expand Down
139 changes: 108 additions & 31 deletions packages/editor/src/components/post-discussion/panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { PanelBody, PanelRow } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import {
Dropdown,
Button,
__experimentalVStack as VStack,
__experimentalText as Text,
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useState, useMemo } from '@wordpress/element';
import { __experimentalInspectorPopoverHeader as InspectorPopoverHeader } from '@wordpress/block-editor';
import { store as coreStore } from '@wordpress/core-data';

/**
* Internal dependencies
Expand All @@ -12,50 +20,119 @@ import { store as editorStore } from '../../store';
import PostTypeSupportCheck from '../post-type-support-check';
import PostComments from '../post-comments';
import PostPingbacks from '../post-pingbacks';
import PostPanelRow from '../post-panel-row';

const PANEL_NAME = 'discussion-panel';

function DiscussionPanel() {
const { isEnabled, isOpened } = useSelect( ( select ) => {
const { isEditorPanelEnabled, isEditorPanelOpened } =
select( editorStore );
function ModalContents( { onClose } ) {
return (
<div className="editor-post-discussion">
<InspectorPopoverHeader
title={ __( 'Discussion' ) }
onClose={ onClose }
/>
<VStack spacing={ 4 }>
<PostTypeSupportCheck supportKeys="comments">
<PostComments />
</PostTypeSupportCheck>
<PostTypeSupportCheck supportKeys="trackbacks">
<PostPingbacks />
</PostTypeSupportCheck>
</VStack>
</div>
);
}

function PostDiscussionToggle( { isOpen, onClick } ) {
const {
commentStatus,
pingStatus,
commentsSupported,
trackbacksSupported,
} = useSelect( ( select ) => {
const { getEditedPostAttribute } = select( editorStore );
const { getPostType } = select( coreStore );
const postType = getPostType( getEditedPostAttribute( 'type' ) );
return {
isEnabled: isEditorPanelEnabled( PANEL_NAME ),
isOpened: isEditorPanelOpened( PANEL_NAME ),
commentStatus: getEditedPostAttribute( 'comment_status' ) ?? 'open',
pingStatus: getEditedPostAttribute( 'ping_status' ) ?? 'open',
commentsSupported: !! postType.supports.comments,
trackbacksSupported: !! postType.supports.trackbacks,
};
}, [] );

const { toggleEditorPanelOpened } = useDispatch( editorStore );

if ( ! isEnabled ) {
return null;
let label;
if ( commentStatus === 'open' ) {
if ( pingStatus === 'open' ) {
label = __( 'Open' );
} else {
label = trackbacksSupported ? __( 'Comments only' ) : __( 'Open' );
}
} else if ( pingStatus === 'open' ) {
label = commentsSupported ? __( 'Pings only' ) : __( 'Pings enabled' );
} else {
label = __( 'Closed' );
}

return (
<PanelBody
title={ __( 'Discussion' ) }
opened={ isOpened }
onToggle={ () => toggleEditorPanelOpened( PANEL_NAME ) }
<Button
size="compact"
className="editor-post-discussion__panel-toggle"
variant="tertiary"
aria-label={ __( 'Change discussion options' ) }
aria-expanded={ isOpen }
onClick={ onClick }
>
<PostTypeSupportCheck supportKeys="comments">
<PanelRow>
<PostComments />
</PanelRow>
</PostTypeSupportCheck>

<PostTypeSupportCheck supportKeys="trackbacks">
<PanelRow>
<PostPingbacks />
</PanelRow>
</PostTypeSupportCheck>
</PanelBody>
<Text>{ label }</Text>
</Button>
);
}

export default function PostDiscussionPanel() {
const { isEnabled } = useSelect( ( select ) => {
const { isEditorPanelEnabled } = select( editorStore );
return {
isEnabled: isEditorPanelEnabled( PANEL_NAME ),
};
}, [] );

// 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 ( ! isEnabled ) {
return null;
}

return (
<PostTypeSupportCheck supportKeys={ [ 'comments', 'trackbacks' ] }>
<DiscussionPanel />
<PostPanelRow label={ __( 'Discussion' ) } ref={ setPopoverAnchor }>
<Dropdown
popoverProps={ popoverProps }
className="editor-post-discussion__panel-dropdown"
contentClassName="editor-post-discussion__panel-dialog"
focusOnMount
renderToggle={ ( { isOpen, onToggle } ) => (
<PostDiscussionToggle
isOpen={ isOpen }
onClick={ onToggle }
/>
) }
renderContent={ ( { onClose } ) => (
<ModalContents onClose={ onClose } />
) }
/>
</PostPanelRow>
</PostTypeSupportCheck>
);
}
26 changes: 26 additions & 0 deletions packages/editor/src/components/post-discussion/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.editor-post-discussion__panel-dialog .editor-post-discussion {
// sidebar width - popover padding - form margin
min-width: $sidebar-width - $grid-unit-20 - $grid-unit-20;
margin: $grid-unit-10;

.components-radio-control__option {
align-items: flex-start;
}

.components-radio-control__label .components-text {
display: block;
margin-top: $grid-unit-05;
}
}
.editor-post-discussion__panel-toggle {
&.components-button {
height: auto;
}
.components-text {
color: inherit;
}
}

.editor-post-discussion__panel-dialog .components-popover__content {
min-width: 320px;
}
13 changes: 11 additions & 2 deletions packages/editor/src/components/post-pingbacks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { CheckboxControl } from '@wordpress/components';
import { CheckboxControl, ExternalLink } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';

/**
Expand All @@ -26,9 +26,18 @@ function PostPingbacks() {
return (
<CheckboxControl
__nextHasNoMarginBottom
label={ __( 'Allow pingbacks & trackbacks' ) }
label={ __( 'Enable pingbacks & trackbacks' ) }
checked={ pingStatus === 'open' }
onChange={ onTogglePingback }
help={
<ExternalLink
href={ __(
'https://wordpress.org/documentation/article/trackbacks-and-pingbacks/'
) }
>
{ __( 'Learn more about pingbacks & trackbacks' ) }
</ExternalLink>
}
/>
);
}
Expand Down
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 @@ -26,7 +26,6 @@ import PageAttributesPanel from '../page-attributes/panel';
import PatternOverridesPanel from '../pattern-overrides-panel';
import PluginDocumentSettingPanel from '../plugin-document-setting-panel';
import PluginSidebar from '../plugin-sidebar';
import PostDiscussionPanel from '../post-discussion/panel';
import PostLastRevisionPanel from '../post-last-revision/panel';
import PostSummary from './post-summary';
import PostTaxonomiesPanel from '../post-taxonomies/panel';
Expand Down Expand Up @@ -120,7 +119,6 @@ const SidebarContent = ( {
<PostTransformPanel />
<PostLastRevisionPanel />
<PostTaxonomiesPanel />
<PostDiscussionPanel />
<PageAttributesPanel />
<PatternOverridesPanel />
{ extraPanels }
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 PostDiscussionPanel from '../post-discussion/panel';
import { PrivatePostExcerptPanel as PostExcerptPanel } from '../post-excerpt/panel';
import PostFeaturedImagePanel from '../post-featured-image/panel';
import PostFormatPanel from '../post-format/panel';
Expand Down Expand Up @@ -80,6 +81,7 @@ export default function PostSummary( { onActionPerformed } ) {
<PostSchedulePanel />
<PostTemplatePanel />
<PostURLPanel />
<PostDiscussionPanel />
<PostSyncStatus />
</VStack>
<PostStickyPanel />
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 @@ -18,6 +18,7 @@
@import "./components/post-actions/style.scss";
@import "./components/post-card-panel/style.scss";
@import "./components/post-content-information/style.scss";
@import "./components/post-discussion/style.scss";
@import "./components/post-excerpt/style.scss";
@import "./components/post-featured-image/style.scss";
@import "./components/post-format/style.scss";
Expand Down
6 changes: 5 additions & 1 deletion test/e2e/specs/editor/various/sidebar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ test.describe( 'Sidebar', () => {
'No Title',
'Categories',
'Tags',
'Discussion',
] );
// Also check 'panels' that are not rendered as TabPanels.
const postExcerptPanel = page.getByRole( 'button', {
Expand All @@ -123,13 +122,17 @@ test.describe( 'Sidebar', () => {
const postFeaturedImagePanel = page.getByRole( 'button', {
name: 'Set featured image',
} );
const postDiscussionPanel = page.getByRole( 'button', {
name: 'Change discussion options',
} );
const postSummarySection = page.getByRole( 'checkbox', {
name: 'Stick to the top of the blog',
} );

await expect( postExcerptPanel ).toBeVisible();
await expect( postFeaturedImagePanel ).toBeVisible();
await expect( postSummarySection ).toBeVisible();
await expect( postDiscussionPanel ).toHaveCount( 1 );

await page.evaluate( () => {
const { removeEditorPanel } =
Expand All @@ -147,5 +150,6 @@ test.describe( 'Sidebar', () => {
await expect( postExcerptPanel ).toBeHidden();
await expect( postFeaturedImagePanel ).toBeHidden();
await expect( postSummarySection ).toBeHidden();
await expect( postDiscussionPanel ).toHaveCount( 0 );
} );
} );

0 comments on commit ef6a1ea

Please sign in to comment.