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

Open up "Pattern Overrides" and therefore intern block bindings to custom dynamic blocks #64870

Open
fabiankaegy opened this issue Aug 28, 2024 · 14 comments
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Block bindings [Feature] Extensibility The ability to extend blocks or the editing experience [Feature] Synced Patterns Related to synced patterns (formerly reusable blocks) [Focus] Blocks Adoption For issues that directly impact the ability to adopt features of Gutenberg. [Type] Enhancement A suggestion for improvement.

Comments

@fabiankaegy
Copy link
Member

fabiankaegy commented Aug 28, 2024

This issue is coming out of a discussion in the Make WordPress Slack Outreach Channel where we discussed some of the reasons why we are not ready to adopt pattern overrides on custom build projects.

Currently, pattern overrides is limited to only a small set of core blocks that have handling for their block bindings HTML replacement handled manually. With that, we have opted not to expose the mechanisms to create blocks that make use of the Pattern Overrides feature publicly until the HTML API lands in core.

However, we just realized that this limitation to wait on the HTML API only really applies to static blocks (ones that serialize their HTML to the database). For dynamic blocks (block rendered via a render_callback in PHP) this limitation does not exist.

Because of that I would propose that we open up the block bindings / pattern overrides feature for custom blocks that use dynamic rendering.

How to achieve that:

First we would need to find a way to indicate which attributes of which blocks actually allow to be bound to something. Currently, this is managed in a hard-coded list. #64756 explores adding a bindable decorator to the attributes definition which could be used to get that list dynamically.

Once we know which attributes of which blocks support bindings, we would need to also use that to handle saving attributes / passing in the correct value of attributes correctly in the editor.

And finally, we can use that same bindable key to replace https://github.com/WordPress/wordpress-develop/blob/e569967ee45e23186f6aa7f479fcb48a7511436b/src/wp-includes/class-wp-block.php#L246-L251 with the dynamic lookup of supported bindings.

@fabiankaegy fabiankaegy added [Type] Enhancement A suggestion for improvement. [Feature] Block API API that allows to express the block paradigm. labels Aug 28, 2024
@fabiankaegy fabiankaegy changed the title Open up "Pattern Overrides" and therefore intern block bindings to custom **dynamic** blocks Open up "Pattern Overrides" and therefore intern block bindings to custom dynamic blocks Aug 28, 2024
@fabiankaegy
Copy link
Member Author

CC: @gziolo @SantosGuillamot since you participated in the conversation in slack :) Would love to get your take on whether I captured things correctly here and to fill in all the nuances that I am missing

@fabiankaegy fabiankaegy moved this to 🗣️ In Discussion / Needs Decision in WordPress 6.7 Editor Tasks Aug 28, 2024
@bph
Copy link
Contributor

bph commented Aug 28, 2024

Also pinging the outreach group @WordPress/outreach to chime in especially on use cases adn further thoughts

@bph bph added [Focus] Blocks Adoption For issues that directly impact the ability to adopt features of Gutenberg. [Feature] Extensibility The ability to extend blocks or the editing experience labels Aug 28, 2024
@fabiankaegy
Copy link
Member Author

fabiankaegy commented Aug 28, 2024

I can chime in and provide some use case examples also :)

First of all, pretty much all blocks we built on custom sites are dynamic block. The reason for this is mostly due to design flexibility with continually changing design requirements.

Some examples of these custom blocks we have on pretty much every project:

  1. Post Picker block
    We have a post picker block that works similar to the post template of the core query. So you can use any of the post level blocks within that block to manage your layout. But instead of being defined by a query, the user can manually search for any articles on their site and reference it. Under the hood all we store in the blocks attributes are the postId and postType.
    It would be super valuable to be able to use this post picker in a synced pattern and then enable overrides so that a user is still able to change the post that gets displayed (this happens via the blocks toolbar and already is setup to work in content only locking)

  2. Icon block
    Similar to the above example we have an Icon block. This icon block allows the user to pick from a predefined set of icons that we bundle with the theme. All we store is the name of the icon.

It would be great be to able to use that inside a synced pattern and enable overrides so that the user can still change the actual icon that should be used whilst all the design options of how large, what color, etc the icon is are still synced.


The end goal that would the make this feature soooooo much more powerful is to allow for all of this in Synced Theme Patterns (#59272)

@colorful-tones
Copy link
Member

I can certainly see how this would be useful. Having the allowed blocks hard-coded is not ideal.

I am confused by

limitation to wait on the HTML API

I thought the HTML API was stable and released back in WP 6.2? 😕

@gziolo
Copy link
Member

gziolo commented Sep 10, 2024

I am confused by

limitation to wait on the HTML API

I thought the HTML API was stable and released back in WP 6.2? 😕

That was HTML Tag Processor in WP 6.2. We are talking about HTML Processor and two features it will allow to support - setInnerHTML method and the ability to convert schema defined by block attributes into the query that should find the proper location in the instance of HTML API:

"href": {
"type": "string",
"source": "attribute",
"selector": "figure > a",
"attribute": "href",
"__experimentalRole": "content"
},

Which would be equivalent to JavaScript:

document.querySelector( 'figure > a' ).href = 'new value';

"caption": {
"type": "rich-text",
"source": "rich-text",
"selector": "figcaption",
"__experimentalRole": "content"
},

Which would be equivalent to JavaScript:

document.querySelector( 'figcaption' ).innerHTML = '<strong>new value</strong>';

@mtias
Copy link
Member

mtias commented Sep 11, 2024

One addendum on the point of role: 'content'—it's not really about serializing static content but about signaling what part of the block should be considered user content so it can be kept while transformed into another block (as part of a larger pattern; without having to know to / from attribute mapping), swapped with another source (bindings), surfaced in content-only scenarios while other roles are discarded, etc.

I'd really like to focus on the semantics of the role and avoid introducing decorator flags like "bindable". The ideal state of this setup is that the role of an attribute signals everything necessary for augmentation.

This will be an important aspect of multilingual as well. The attributes designated as "content" would be the immediate candidates for localization.

The more this is architected around the topology of the role itself and less about operational flags the more it simplifies adoption and the overall clarity for extenders. It's a do more with less kind of thing.

@fabiankaegy
Copy link
Member Author

@mtias thank you for chiming in here. I’m not sure I understand how the full spectrum of which fields should be bindable etc, which should be translatable etc can be accomplished by one single content role.

As an example, we have an icon block that stores a slug of a selected icon as an attribute. This attribute should still be changeable by a user when inside a content only locked section or a pattern override. However it is not something that should get translated. So at least for that stage I personally believe that we will need some kind of operators to opt out of things like translatable for example.

And the same goes for transforms. I’m not sure how just having content as an available role is enough. Using this same example of the icon block. If that slug is marked as content because its the only way to make it bindable, then swapping the pattern it it in could result in that slug now becoming a heading / paragraph of some kind…

so if we want to make all this derived I think the we at least need more different kinds of roles. Maybe even a way to register custom roles / manage what properties are derived for each role.

@gziolo
Copy link
Member

gziolo commented Sep 11, 2024

Thank you for the clarification, @mtias. __experimentalRole is not documented, so it’s open to interpretation. In that case, I would be in favor of gradually promoting __experimentalRole to role and documenting the property while inheriting support for Block Bindings when that role is defined. In this context, it also means that role content can be applied to any attribute, like in the case of dynamic blocks discussed in this issue.

I'd really like to focus on the semantics of the role and avoid introducing decorator flags like "bindable". The ideal state of this setup is that the role of an attribute signals everything necessary for augmentation.

I'm in favor of providing a good default where content means:

  • transformations enabled
  • bindings enabled
  • translations enabled

I think it also does some magic with patterns. I don't remember what exactly, though 😅

so if we want to make all this derived I think the we at least need more different kinds of roles. Maybe even a way to register custom roles / manage what properties are derived for each role.

That sounds like an interesting path to explore that would remove the need to introduce multiple boolean flags in the attribute's schema. It's worth highlighting, there is also __experimentalRole: local introduced by @youknowriad that has also some special meaning. So that can become difficult to mange taking into account all possible edge cases raised by @fabiankaegy. We can move that discussion also to #64756 if that is more appropriate.

@ndiego
Copy link
Member

ndiego commented Sep 11, 2024

Just wanted to echo @fabiankaegy's comments above. I experimented with making my own icon block editable when contentOnly is enabled. The code is here.

Whatever the final outcome is, I plan to cover this on the Developer Blog (WordPress/developer-blog-content#303).

@noisysocks noisysocks moved this from 🗣️ In Discussion / Needs Decision to 🏈 Punted to 6.8 in WordPress 6.7 Editor Tasks Sep 17, 2024
@gziolo
Copy link
Member

gziolo commented Sep 20, 2024

I see that @getdave is working on making the role property stable:

Great timing. I’ll see if we can connect that change with ensuring it’s used as an indicator for Block Bindings based on the conditions discussed in this issue.

@talldan, does Pattern Overrides use the role content with the __default special operator?

@talldan
Copy link
Contributor

talldan commented Sep 30, 2024

@talldan, does Pattern Overrides use the role content with the __default special operator?

At the moment the pattern block uses setBlockEditingMode( clientId, 'contentOnly' ) for it's inner blocks, so it doesn't use role: 'content' at all. I was looking at changing that in #65408 (PR needs a rebase).

@fabiankaegy
Copy link
Member Author

@talldan But under the hood contentOnly locking uses the role: 'content' still to determine which UI is exposed / editable? 🤔

@talldan
Copy link
Contributor

talldan commented Sep 30, 2024

Yep!

Apart from the List Block, which has some special logic that needs to be reviewed.

@getdave
Copy link
Contributor

getdave commented Oct 1, 2024

@fabiankaegy Yes it does:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Block bindings [Feature] Extensibility The ability to extend blocks or the editing experience [Feature] Synced Patterns Related to synced patterns (formerly reusable blocks) [Focus] Blocks Adoption For issues that directly impact the ability to adopt features of Gutenberg. [Type] Enhancement A suggestion for improvement.
Projects
Status: 🏈 Punted to 6.8
Development

No branches or pull requests

8 participants