Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group block: use a variation picker in the placeholder #43496

Merged
merged 24 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
cdacf9e
Group block: remove default layout for the group block and use a vari…
ramonjd Aug 23, 2022
b25f7ea
Updating e2e tests to select default group from group variation place…
ramonjd Aug 23, 2022
323545c
Adding meaningful aria label to block variation picker
ramonjd Aug 24, 2022
bd309ce
Only you..... can make my tests go green....
ramonjd Aug 24, 2022
85f4018
Clicking on block variation skip button
ramonjd Aug 24, 2022
fcde025
Clicking on block variation skip
ramonjd Aug 24, 2022
a9c623e
Programmatically creating a group block will not default to the const…
ramonjd Aug 25, 2022
5f5d5a5
Reinstating default "constrained" layout type, but adding an extra ep…
ramonjd Aug 25, 2022
4ef0d75
Ensure that the inserted block is selected after a Group variation is…
ramonjd Sep 6, 2022
435c42b
Removing skip link and update description
ramonjd Sep 6, 2022
506162d
Reinstate skip for now until we can update the e2e tests
ramonjd Sep 6, 2022
b5d878d
Stylising the placeholder icons
ramonjd Sep 7, 2022
c6771d6
Adding `isDefault` to the default props and removing it when a group …
ramonjd Sep 21, 2022
dbdc9c4
Updating tests to account for:
ramonjd Sep 21, 2022
ed855ec
Creating a custom group block variation picker so we do not have to u…
ramonjd Oct 25, 2022
87aa63e
Add missing button label.
ramonjd Oct 25, 2022
5c6cfa6
Update native test fixture
ramonjd Oct 27, 2022
8960635
Removing the `isDefault` Group block attribute. It's a fragile soluti…
ramonjd Nov 2, 2022
af0be48
Ensure that we select the default group variation in the e2e tests.
ramonjd Nov 2, 2022
c84bf8e
Creating custom hook for `showPlaceholder`
ramonjd Nov 3, 2022
72d227c
Default selected layout type of Group variation is "constrained"
ramonjd Nov 3, 2022
bdb8515
Am I pretty enough for you, linter?
ramonjd Nov 4, 2022
6d8bc19
Reverted
ramonjd Nov 4, 2022
4f1fd81
Reinstating `useEffect` so that we can react to changes in the style …
ramonjd Nov 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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