-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Implement nesting in cover image block #5452
Conversation
e5d3504
to
83a729c
Compare
Related: #4097 (as far as prior art in restricting block types shown in the inserter) |
@jorgefilipecosta looking forward to this :) Thanks! |
386c376
to
e3ee131
Compare
e3ee131
to
98b78d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work here 👍
.editor-block-list__layout { | ||
width: 100%; | ||
.editor-block-list__block:not(.is-multi-selected) .wp-block-paragraph { | ||
background: none; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we use a background on the paragraph block by default? I'm trying to understand why this is needed mainly to avoid the specificity to target the paragraph block's className in another block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @youknowriad,
The reason why we set a white background is related to the contrast verification. If the background was never set getComputedStyles returns back background (if I remember correctly). So adding a background fixes the problem. If themes change the background it also works well because as long as a background is set we are able to retrieve it. The problem happens when no background is set. As we get back background color when background is not set we cannot differentiate and assume is white background because in fact it may be set to black. I will try to research this in more detail maybe there is a way to detect when the background is not set and in that case assume white.
Replicate from comment #5273 (comment).
A refactoring will happen to contrast checker in order to not rely on this rule. So it will be removed for now.
blocks/library/cover-image/index.js
Outdated
textColor: '#fff', | ||
} ], | ||
] } | ||
allowedBlockNames={ [ 'core/button', 'core/heading', 'core/paragraph', 'core/subhead' ] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️ awesome API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move it to the settings object in registerBlockType
to make it extensible? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant both template
and allowedBlockNames
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted in the description, this allows it to be customizable using toolbar/inspector controls.
But this makes me think of something. We should consider the template
prop here as a defaultTemplate
because we already have support for nested template. by setting a CPT template with a nested template for the cover image for instance. I think we should do something here where the template prop is used (override it by the global template if available or something)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m missing something here, how can I override those values for Cover Image block? 😄
I couldn't digest this from this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okey, I know what you were referring to. You should be able to do it when providing the template for CPT as explained in here: https://wordpress.org/gutenberg/handbook/templates/#nested-templates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we switch this API to be allowedBlocks
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @youknowriad,
But this makes me think of something. We should consider the template prop here as a defaultTemplate because we already have support for nested template. by setting a CPT template with a nested template for the cover image for instance. I think we should do something here where the template prop is used (override it by the global template if available or something).
When we have a CPT template and we set content for a nested block, ( e.g: we set a cover image with a header and a paragraph), during the post-load the cover image is created and the blocks are added inside it. So when our inner logic executes the cover image block already has content, so the template will not be used. It will be the same as when we load a post with a cover image that already has blocks inside it. The template only applies to empty blocks.
So both approaches can work together without problems if a global template exists it already overwrites this setting :)
Hi @mtias the prop was renamed to allowedBlocks.
editor/store/reducer.js
Outdated
@@ -976,13 +976,41 @@ export const reusableBlocks = combineReducers( { | |||
}, | |||
} ); | |||
|
|||
export const blockListSettings = ( state = {}, action ) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a docBlock to explain what's this reducer for?
insertTemplateBlocksIfInnerBlocksEmpty( template ) { | ||
const { block, onInsertBlocks, uid } = this.props; | ||
if ( template && ! block.innerBlocks.length ) { | ||
onInsertBlocks( synchronizeBlocksWithTemplate( [], template ), 0, uid ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think synchronizing the template is not needed here because we only synchronize templates if the template is locked but we don't support locking yet for inner Blocks.
Unless I'm missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes synchronizing the template is not needed. But I want to given a template parse and create the block structure it represents turns out that's exactly what synchronizeBlocksWithTemplate( [], template )
does so I did not want to duplicate code and used it :)
editor/utils/block-list.js
Outdated
} | ||
|
||
componentWillReceiveProps( nextProps ) { | ||
updateNestedSettingsIfNeeded( { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far As I understand we have the uid
at this point, so we can call the action directly in this component to avoid the need to add a new callback to this HoC?
editor/utils/block-list.js
Outdated
updateNestedSettingsIfNeeded( { | ||
supportedBlocks: this.props.allowedBlockNames, | ||
} ); | ||
insertTemplateBlockIfNeeded( this.props.template ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for this callback: can w call the action directly in this component to avoid the need to add a new callback to this HoC?
( state, { globalEnabledBlockTypes } ) => { | ||
const insertionPoint = getBlockInsertionPoint( state ); | ||
const { rootUID } = insertionPoint; | ||
const blockListSettings = getBlockListSettings( state, rootUID ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could move this logic to a selector to test it properly:
getSupportBlocks( state, uid, enabledBlockTypes )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second that 👍
editor/components/inserter/index.js
Outdated
@@ -79,19 +80,25 @@ class Inserter extends Component { | |||
onClose(); | |||
}; | |||
|
|||
return <InserterMenu onSelect={ onSelect } />; | |||
return <InserterMenu onSelect={ onSelect } supportedBlockTypes={ supportedBlockTypes } />; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this prop is not used in the current component, can we move to the menu component instead?
Also might be good to factorize, using the selector proposed above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @youknowriad, the prop supportedBlockTypes is used to compute hasSupportedBlocks flag that's why it was computed in this component.
Regarding the factorize to selector, I will try to make this more generic maybe it will involve selector plus HoC that accesses the context.
It doesn't look that bad, it is similar to what is used in config files for libraries like Babel. See: https://github.com/WordPress/packages/blob/master/packages/babel-preset-default/index.js#L6-L11 |
blocks/library/cover-image/index.js
Outdated
url: { | ||
type: 'string', | ||
}, | ||
align: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think align
should stay in here. Otherwise, it won't be possible to change the alignment of the container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the idea I have in mind is that it is no possible to change the alignment of the container. The container takes 100% width. So for example, if we want to right align text we apply the alignment on the nested paragraph block.
Edited: sorry I understood what you mean, you are totally right it was a mistake. This attribute should not be removed.
blocks/library/cover-image/index.js
Outdated
const controls = isSelected && [ | ||
<BlockControls key="controls"> | ||
<BlockAlignmentToolbar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same applies in here, unless it is moved to the InnerBlock. In that case validAlignments
and getEditWrapperProps
might need to be removed.
blocks/library/cover-image/index.js
Outdated
textColor: '#fff', | ||
} ], | ||
] } | ||
allowedBlockNames={ [ 'core/button', 'core/heading', 'core/paragraph', 'core/subhead' ] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m missing something here, how can I override those values for Cover Image block? 😄
I couldn't digest this from this PR.
001ea8f
to
0fc0bd5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few comments to check.
blocks/library/cover-image/index.js
Outdated
[ 'core/paragraph', { | ||
align: 'center', | ||
fontSize: 37, | ||
placeholder: 'Write title…', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Translation wrapper missing for placeholder.
blocks/library/cover-image/index.js
Outdated
template={ [ | ||
[ 'core/paragraph', { | ||
align: 'center', | ||
fontSize: 37, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Font size has now this t-shirt like sizes, is it one of them?
editor/utils/block-list.js
Outdated
componentWillMount() { | ||
INNER_BLOCK_LIST_CACHE[ uid ][ 1 ]++; | ||
} | ||
connect( ( state ) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a good practice to stop using connect in favor of withSelect snd withDispatch HOCs.
( state, { globalEnabledBlockTypes } ) => { | ||
const insertionPoint = getBlockInsertionPoint( state ); | ||
const { rootUID } = insertionPoint; | ||
const blockListSettings = getBlockListSettings( state, rootUID ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second that 👍
<!-- wp:core/cover-image {"url":"https://cldup.com/uuUqE_dXzy.jpg","dimRatio":40} --> | ||
<div class="wp-block-cover-image has-background-dim-40 has-background-dim" style="background-image:url(https://cldup.com/uuUqE_dXzy.jpg)"> | ||
<p class="wp-block-cover-image-text">Guten Berg!</p> | ||
<!-- wp:cover-image {"url":"https://cldup.com/uuUqE_dXzy.jpg","id":8398} --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
has-undefined-content
is here because contenAlign
attribute was removed, but not its corresponding class name.
"hasParallax": false, | ||
"dimRatio": 40 | ||
"dimRatio": 50 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be nice to keep non-default dim to see the class name included in HTML.
<div class="wp-block-cover-image has-background-dim has-undefined-content" style="background-image:url(https://cldup.com/uuUqE_dXzy.jpg)"> | ||
<div class="wp-block-cover-image__inner-container"> | ||
<!-- wp:paragraph {"align":"center","placeholder":"Write title…","textColor":"#fff","fontSize":37} --> | ||
<p style="color:#fff;text-align:center">Paragraph 1</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it expected that fot size is not printed as style?
f854e6b
to
a9a596f
Compare
Hi @gziolo and @youknowriad thank you a lot for the feedback it was applied. |
Wanted to note that I'm doing some work in #6406 that might benefit some of the color/UI issues. |
f922df2
to
e68c355
Compare
Hi @mcsf, the rebase was done. I think this should ready. I'm solving some accessibility issues using other PR's (as they are not exclusive in this PR). |
Hi @jasmussen, thank you for the improvements you are making they will make nesting in colored places like cover image better. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think whilst it's not perfect visually getting this in and refining with the work @jasmussen is doing there, is the best route. As a result approving this and let's note though in merge that this is to be refined, just to set expectations.
Since this is a pretty complex PR, should we wait for Matías technical thoughts? He's AFK but hopefully back next week. It feels like his comments starting in #5452 (comment) were sort of skeptical. Not saying because this isn't impressive work, just wondering. |
Adds a set of Gutenberg "Form" blocks for use with the contact form module. Blocks: * Form - The main block, consists of an InnerBlock for the <form> element and a set template consisting of a default set of inner blocks preconfigured as a contact form * Text - General <input type=text>/<textarea> field with configurable label, rows * Button - A <button type=submit> with configurable button text Blocking Release: * InnerBlock templating requires WordPress/gutenberg#5452. * WordPress/gutenberg#5452 needs to override isPrivate settings to prevent form blocks being seen in the inserter when out of form context. * WordPress/gutenberg#5452 is whitelist only meaning we cant add extra blocks in between form elements - not really a huge issue for this but likely an issue for other use cases. Todo - Integration with grunion-contact-form: * Captcha support should be relatively easy to achieve with a serverside rendered block * A server side filter / hook could replace the form action Todo - Handle duplicate field names gracefully * Currently uses a variation on the label / field name to set id / for settings on label / inputs. * Currently uses same variation for <input name=""> attributes
e68c355
to
9d56d9a
Compare
@jorgefilipecosta - can you rebase with the recent changes from @mtias - it waits for your feedback. |
Should this be added to the Merge Proposal: Editor milestone? It seems like something that would be good for optimum recreation of existing content into Gutenberg block form. |
Context: #9452 @oskosk Requested this unfinished branch to be pushed up to Automattic/jetpack for use in the Jetpck Beta Tester Plugin. -- Adds a set of Gutenberg "Form" blocks for use with the contact form module. Blocks: * Form - The main block, consists of an InnerBlock for the <form> element and a set template consisting of a default set of inner blocks preconfigured as a contact form * Text - General <input type=text>/<textarea> field with configurable label, rows * Button - A <button type=submit> with configurable button text Blocking Release: * Fix issues identified in original PR #9452 * InnerBlock templating requires WordPress/gutenberg#5452. * WordPress/gutenberg#5452 needs to override isPrivate settings to prevent form blocks being seen in the inserter when out of form context. * WordPress/gutenberg#5452 is whitelist only meaning we cant add extra blocks in between form elements - not really a huge issue for this but likely an issue for other use cases. Todo - Integration with grunion-contact-form: * Captcha support should be relatively easy to achieve with a serverside rendered block * A server side filter / hook could replace the form action Todo - Handle duplicate field names gracefully * Currently uses a variation on the label / field name to set id / for settings on label / inputs. * Currently uses same variation for <input name=""> attributes
I think the Cover Image block would be made redundant by the existence of a Container block. The Cover Image concept could just be a Reusable block inserted as a template. Think about it. Every setting for the Cover Image block would work for a Container block, and adding nesting to the Cover Image block just makes it into a sort of container block anyway. See also: |
Description
This PR implements the concepts described in #5448.
E.g:
As future work template_lock will be added. This opens the path for a whole new type of blocks.
Blocks that make use of nesting and just apply a special arrangement/design to existing blocks.
E.g: we can have a package of landing page blocks, where all of the blocks are based on paragraphs, headings, buttons etc... arranging them in a special way and applying some styles. Themes may take advantage of this to create theme-specific blocks.
The fact that the InnerBlocks settings are just props has some advantages e.g: depending on the settings in the block inspector we may allow different blocks. But it is much more complex to implement when compared to
Add a property to the block API, allowedRootBlockNames: [ ... ]
.Right now this implementation is not very clean ( being nice to myself ) we are using a property in the state the save the current InnerBlock settings of each block uid with custom settings. This was required because we need to globally know the allowed blocks, so the inserter can filter them. Maybe there is a better way to solve this problem. I'm thinking about an impossible way to improve this and I'm totally open to suggestions.
To define templates we are using the same logic as the one used in CPT's but this makes the data structure strange in javascript (until know templates were only defined in PHP so this was unnoticeable).
Cover image block was updated to make use of this concepts.
Know problems / related work
Using the autocomplete, we can insert allowed blocks. Autocomplete logic is different from other inserters and we already have some problems e.g: if the template lock the blocks, autocomplete inserter is not aware of the lock and then we get a big js error because onReplace does not exist in this case. In parallel, I will improve the logic of autocomplete inserter so changes required here are easier.
Testing
Test the cover image block try to add blocks remove see things work as expected. The design will benefit from #5658.
Test that templates also work with layouts by adding this template to columns block.
Test that we are backcompatible with existing cover images by pasting the following code in the code editor and verifying it works as expected:
Screenshots (jpeg or gifs if applicable):