Skip to content

Commit

Permalink
Group block: use a variation picker in the placeholder (#43496)
Browse files Browse the repository at this point in the history
* Group block: remove default layout for the group block and use a variation picker in the placeholder.

* Updating e2e tests to select default group from group variation placeholder

* Adding meaningful aria label to block variation picker
Updating e2e tests
Refactoring Group edit.js

* Only you..... can make my tests go green....

* Clicking on block variation skip button

* Clicking on block variation skip

* Programmatically creating a group block will not default to the constrained layout type. It must be specified.

* Reinstating default "constrained" layout type, but adding an extra ephemeral property to identify blocks that have been inserted.

* Ensure that the inserted block is selected after a Group variation is selected.

* Removing skip link and update description

* Reinstate skip for now until we can update the e2e tests

* Stylising the placeholder icons
updating tests

* Adding `isDefault` to the default props and removing it when a group variation is selected.

* Updating tests to account for:
- default layout is "constrained" when programmatically inserting a group block
- using createBlock with no attributes passed

* Creating a custom group block variation picker so we do not have to update (and potentially break) the blockvariationpicker component, which is used elsewhere.

* Add missing button label.
Add class to button.
Fix outline heights for button.

* Update native test fixture

Updating design/spacing of placeholder
Hardcoding custom icons

* Removing the `isDefault` Group block attribute. It's a fragile solution to keep track of whether a variation has been selected since it adds a potentially useless attribute.
In this iteration, we'll keep track of whether to show the placeholder via useState in the editor, and, more permanently, whether the block has innerblocks.

* Ensure that we select the default group variation in the e2e tests.

* Creating custom hook for `showPlaceholder`
Testing on the CI whether the changes to CPT are required :)

* Default selected layout type of Group variation is "constrained"

* Am I pretty enough for you, linter?

* Reverted

* Reinstating `useEffect` so that we can react to changes in the style state.
  • Loading branch information
ramonjd committed Nov 15, 2022
1 parent 370c7c0 commit 4f25464
Show file tree
Hide file tree
Showing 11 changed files with 446 additions and 50 deletions.
139 changes: 95 additions & 44 deletions packages/block-library/src/group/edit.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

import { useDispatch, useSelect } from '@wordpress/data';
import {
InnerBlocks,
useBlockProps,
Expand All @@ -13,30 +12,67 @@ import {
} from '@wordpress/block-editor';
import { SelectControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useCallback } from '@wordpress/element';

const htmlElementMessages = {
header: __(
'The <header> element should represent introductory content, typically a group of introductory or navigational aids.'
),
main: __(
'The <main> element should be used for the primary content of your document only. '
),
section: __(
"The <section> element should represent a standalone portion of the document that can't be better represented by another element."
),
article: __(
'The <article> element should represent a self contained, syndicatable portion of the document.'
),
aside: __(
"The <aside> element should represent a portion of a document whose content is only indirectly related to the document's main content."
),
footer: __(
'The <footer> element should represent a footer for its nearest sectioning element (e.g.: <section>, <article>, <main> etc.).'
),
};
/**
* Internal dependencies
*/
import GroupPlaceHolder, { useShouldShowPlaceHolder } from './placeholder';

/**
* Render inspector controls for the Group block.
*
* @param {Object} props Component props.
* @param {string} props.tagName The HTML tag name.
* @param {Function} props.onSelectTagName onChange function for the SelectControl.
*
* @return {JSX.Element} The control group.
*/
function GroupEditControls( { tagName, onSelectTagName } ) {
const htmlElementMessages = {
header: __(
'The <header> element should represent introductory content, typically a group of introductory or navigational aids.'
),
main: __(
'The <main> element should be used for the primary content of your document only. '
),
section: __(
"The <section> element should represent a standalone portion of the document that can't be better represented by another element."
),
article: __(
'The <article> element should represent a self-contained, syndicatable portion of the document.'
),
aside: __(
"The <aside> element should represent a portion of a document whose content is only indirectly related to the document's main content."
),
footer: __(
'The <footer> element should represent a footer for its nearest sectioning element (e.g.: <section>, <article>, <main> etc.).'
),
};
return (
<InspectorControls __experimentalGroup="advanced">
<SelectControl
label={ __( 'HTML element' ) }
options={ [
{ label: __( 'Default (<div>)' ), value: 'div' },
{ label: '<header>', value: 'header' },
{ label: '<main>', value: 'main' },
{ label: '<section>', value: 'section' },
{ label: '<article>', value: 'article' },
{ label: '<aside>', value: 'aside' },
{ label: '<footer>', value: 'footer' },
] }
value={ tagName }
onChange={ onSelectTagName }
help={ htmlElementMessages[ tagName ] }
/>
</InspectorControls>
);
}

function GroupEdit( {
attributes,
name,
setAttributes,
clientId,
__unstableLayoutClassNames: layoutClassNames,
Expand All @@ -52,18 +88,26 @@ function GroupEdit( {
},
[ clientId ]
);
const defaultLayout = useSetting( 'layout' ) || {};

const { tagName: TagName = 'div', templateLock, layout = {} } = attributes;

// Layout settings.
const defaultLayout = useSetting( 'layout' ) || {};
const usedLayout = ! layout?.type
? { ...defaultLayout, ...layout, type: 'default' }
: { ...defaultLayout, ...layout };
const { type = 'default' } = usedLayout;
const layoutSupportEnabled = themeSupportsLayout || type === 'flex';

// Hooks.
const blockProps = useBlockProps( {
className: ! layoutSupportEnabled ? layoutClassNames : null,
} );

const [ showPlaceholder, setShowPlaceholder ] = useShouldShowPlaceHolder( {
attributes,
usedLayoutType: usedLayout?.type,
hasInnerBlocks,
} );
const innerBlocksProps = useInnerBlocksProps(
layoutSupportEnabled
? blockProps
Expand All @@ -78,31 +122,38 @@ function GroupEdit( {
}
);

const { selectBlock } = useDispatch( blockEditorStore );
const updateSelection = useCallback(
( newClientId ) => selectBlock( newClientId, -1 ),
[ selectBlock ]
);
const selectVariation = ( nextVariation ) => {
setAttributes( nextVariation.attributes );
updateSelection( clientId );
setShowPlaceholder( false );
};

return (
<>
<InspectorControls __experimentalGroup="advanced">
<SelectControl
label={ __( 'HTML element' ) }
options={ [
{ label: __( 'Default (<div>)' ), value: 'div' },
{ label: '<header>', value: 'header' },
{ label: '<main>', value: 'main' },
{ label: '<section>', value: 'section' },
{ label: '<article>', value: 'article' },
{ label: '<aside>', value: 'aside' },
{ label: '<footer>', value: 'footer' },
] }
value={ TagName }
onChange={ ( value ) =>
setAttributes( { tagName: value } )
}
help={ htmlElementMessages[ TagName ] }
<GroupEditControls
tagName={ TagName }
onSelectTagName={ ( value ) =>
setAttributes( { tagName: value } )
}
/>
{ showPlaceholder && (
<GroupPlaceHolder
clientId={ clientId }
name={ name }
onSelect={ selectVariation }
/>
</InspectorControls>
{ layoutSupportEnabled && <TagName { ...innerBlocksProps } /> }
) }
{ layoutSupportEnabled && ! showPlaceholder && (
<TagName { ...innerBlocksProps } />
) }
{ /* Ideally this is not needed but it's there for backward compatibility reason
to keep this div for themes that might rely on its presence */ }
{ ! layoutSupportEnabled && (
{ ! layoutSupportEnabled && ! showPlaceholder && (
<TagName { ...blockProps }>
<div { ...innerBlocksProps } />
</TagName>
Expand Down
48 changes: 48 additions & 0 deletions packages/block-library/src/group/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,51 @@
pointer-events: all;
}
}

.wp-block-group__placeholder {
.wp-block-group-placeholder__variations {
list-style: none;
display: flex;
justify-content: center;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
padding: 0;
margin: 0;
}
.components-placeholder__instructions {
text-align: center;
margin-bottom: 18px;
}
.wp-block-group-placeholder__variations svg {
fill: $gray-400 !important;
}
.wp-block-group-placeholder__variations svg:hover {
fill: var(--wp-admin-theme-color) !important;
}
.wp-block-group-placeholder__variations > li {
margin: 0 $grid-unit-15 $grid-unit-15 $grid-unit-15;
width: auto;
display: flex;
flex-direction: column;
align-items: center;
}
.wp-block-group-placeholder__variations li > .wp-block-group-placeholder__variation-button {
width: 44px;
height: 32px;
padding: 0;
&:hover {
box-shadow: none;
}
}
.components-placeholder {
min-height: auto;
padding: $grid-unit-30;
}
.is-small,
.is-medium {
.wp-block-group-placeholder__variations > li {
margin: $grid-unit-15;
}
}
}
Loading

0 comments on commit 4f25464

Please sign in to comment.