WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.46k stars 4.18k forks source link

Variations (formerly patterns) API for blocks #16283

Closed youknowriad closed 4 years ago

youknowriad commented 5 years ago

(Related design explorations for Block Patterns https://github.com/WordPress/gutenberg/issues/17335.)

Description

A lot of block use the "setup state" pattern where some options/layouts are shown to the block user while inserterting the block:

Capture d’écran 2019-06-25 à 2 41 47 PM

All these are similar in behavior. The user picks a variation and this variation applies initial attributes and innerBlocks content to the selected block.

The idea of this issue is to generalize that concept. Similarily to how we define block style variations, a block type should be able to define Block Variations the user could pick from.

API

The API could look something like this:

const blockTypeSettings = {
   // ...
   variations: [
       { name: __( 'Two columns; equal split' ), innerBlocks: [ ['core/column'], ['core/column'] ] },
       { name: __( 'Three columns; equal split' ), innerBlocks: [ ['core/column'], ['core/column'], ['core/column'] ] },
   ]

The variations can also define just attributes

 // ...
   variations: [
       { name: __( 'Big Quote' ), attributes: { size:'big' } },
       { name: __( 'Small Quote' ), attributes: { size:'small' } },
   ]

These are just examples to illustrate the API and not a final design.

We'd also probably need APIs to register/unregister these variations (similar to the style variations).

UI

In terms of UI, we could explore different possibilities:

Related #16129

Current Tasks

  1. [x] Create an API for registering variations very close to block styles (#18270).
  2. [x] Refactor Columns block to use this new API making the placeholder open for customization (#18283).
  3. [x] Refactor more blocks that fit like:
    • [x] ~Media+Text~ (#18343) – closed as UX wasn't great
    • [x] ~Table~ – it doesn't seem to be a good idea
    • [x] ~Cover~ – it doesn't seem to be a good idea
  4. [x] Explore how we can modify the search logic in the inserter to match blocks through variations as proposed by @kjellr (#19243).
  5. [x] Rename the API from patterns to variations (#19966).
  6. [x] Blocks: Promote block variations to stable API (#20068).
  7. [x] Add three e2e tests that use example scenarios listed in the description of #20068 (#20286).
  8. [x] Block API docs should be updated to include details about this new API (#20145).
  9. [ ] Adding a tutorial for users would be fantastic.
  10. [ ] Extract common logic as an initial screen for blocks that define variations.
  11. [ ] Integrate variations with the / inserter.
  12. [ ] Explore how it could be embedded in the block inspector.
  13. [ ] Explore how blocks could inform about the variation applied.
klihelp commented 5 years ago

Good idea the initial "setup state". Thank you for the grat setup state on the columns block.

kjellr commented 5 years ago

👋 I'd like to get the design leg of this started with a few thoughts, examples, and questions.

As Riad noted above, this is an expansion of the columns work added in #15663:

Frame 2

Here are a handful of potential use cases for this same pattern in core blocks:

Example - Cover Example - Latest Posts Example - Media Text Example - Table

This isn't necessarily limited to layout though — theoretically, blocks could use this to allow users to choose any sort of default state for their block. A couple possible ideas:

Example - Map Example - Form

In many cases, it'll make sense to include these options in the setup state. Beyond that, they'll likely also need to live in either the Block Switcher menu, or in the Sidebar:

Layout Options in the Sidebar:

03

Layout Options in the Block Switcher:

Frame 2 1

Questions

  1. From a user perspective, how are these different from Block Styles? Depending on the treatment and placement of these options, I could see many of them being analogous: The two Quote block styles for instance feel very much like layouts. Should blocks be able to present Block Styles in the placeholder state?
  2. In the placeholder state, should we include the option of a multi-step process? In #15663, we opted to keep the layout options confined to a single screen. I'm of the mind that this is generally the best approach for simplicity's sake, but we know some 3rd party blocks have found uses for multi-step placeholders (I'd love to hear thoughts from @richtabor here, since I know CoBlocks makes use of this pattern).
  3. In addition to the placeholder, does it make sense to include these options in the Sidebar, or in the Block Switcher dropdown (or both)? I think the sidebar makes more sense personally. In the case of the columns block for instance, the sidebar allows for there to be separate controls for number of columns and column layout.
  4. You'll note in the comps above, one of the options is highlighted with darker, thicker border. This is to denote the default/suggested state. This may not be 100% necessary, but I do think it helps direct the user a little bit. The visual treatment is something that's being explored in https://github.com/WordPress/gutenberg/issues/15906#issuecomment-508129512, as it has broader implications for other areas of the UI. Please weigh in there with any thoughts.

Anything I'm missing? Looking forward to discussion around this. 🙂

youknowriad commented 5 years ago

I love those explorations ❤️

From a user perspective, how are these different from Block Styles? Depending on the treatment and placement of these options, I could see many of them being analogous: The two Quote block styles for instance feel very much like layouts. Should blocks be able to present Block Styles in the placeholder state?

I think the main difference is that a block style is never a destructive change. All content/attributes/options are there while choosing a different pattern can result in sub-blocks being removed, content being changed...

kjellr commented 5 years ago

I think the main difference is that a block style is never a destructive change. All content/attributes/options are there while choosing a different pattern can result in sub-blocks being removed, content being changed...

That's a good point. It makes me think that these will need a really clear name, to differentiate them from Block Styles... We'll have to think through that a bit too.

mtias commented 5 years ago

This is great, thanks for exploring the variations. The transforms menu is potentially becoming a bit unwieldy: it includes block transforms, block styles, and now these new layout options. How can we make it more clear and functional? Should we split things out of it?

karmatosed commented 5 years ago

This is great, thanks for exploring the variations. The transforms menu is potentially becoming a bit unwieldy: it includes block transforms, block styles, and now these new layout options. How can we make it more clear and functional? Should we split things out of it?

This is a really key point to me, right now they are being hidden. I have found so many people don't even notice there are styles. Hiding layout under this could lead to yet another really powerful feature being hidden.

Out there idea, are these all 3 separate enough to want different locations? I can see perhaps styling and layout being 'similar' but I do come back to maybe they just are all separate actions that need to be ensured to be surfaced.

richtabor commented 5 years ago

2. In the placeholder state, should we include the option of a multi-step process? In #15663, we opted to keep the layout options confined to a single screen. I'm of the mind that this is generally the best approach for simplicity's sake, but we know some 3rd party blocks have found uses for multi-step placeholders (I'd love to hear thoughts from @richtabor here, since I know CoBlocks makes use of this pattern).

I'd say having something in place for folks who need multi-step would be nice to have, further encouraging developers to utilize core components and patterns. I don't think we should back ourselves into a corner for simplicity's sake, as we know blocks will continue to get more and more advanced as Gutenberg, and more importantly JS WordPress developers, mature.

chrisvanpatten commented 5 years ago

I really like the look in the startup state, but have some doubts about putting these options in the block switcher, or allowing them in general after a block is set up. The idea that these could be destructive is a bit concerning. Even with a robust undo system, it seems like this could create more problems than it solves, and make people inherently less likely to use the feature.

kjellr commented 5 years ago

The transforms menu is potentially becoming a bit unwieldy: it includes block transforms, block styles, and now these new layout options.

This is a really key point to me, right now they are being hidden. I have found so many people don't even notice there are styles. Hiding layout under this could lead to yet another really powerful feature being hidden.

Yeah — I mocked it up, but I don't think it makes sense for these to live in the block switcher, for many of the reasons above. The Block Switcher menu is becoming a bit of a "Junk drawer" of features: Switch to a different type of block, create a group, switch styles, etc. If blocks want to include the ability to adjust these layouts after the setup state (more on that below), I think the sidebar is the place for it.

The idea that these could be destructive is a bit concerning. Even with a robust undo system, it seems like this could create more problems than it solves, and make people inherently less likely to use the feature.

I think it's important to note that the ability to change layout post-placeholder state should be up to the block. For some (like media + text for instance), it makes sense to allow it. But for other blocks (like the form block example above), it won't. Block authors should be able to opt-out as needed.

mtias commented 5 years ago

Block transformations are already lossy, so in that sense I don't see layout transformations as that different.

One thing I'd also like to consider in the exploration is how to surface certain layout / pattern configurations before you insert a block, to help with discovery. For example, a "Form" block could have pre-defined sets using this new API for "Contact Us", "Feedback", and so on. Can you discover these by searching? Would a two step-insertion make sense in the inserter (so first click is on "Form" and second is on one of the pre-arranged templates).

kjellr commented 5 years ago

One thing I'd also like to consider in the exploration is how to surface certain layout / pattern configurations before you insert a block, to help with discovery. For example, a "Form" block could have pre-defined sets using this new API for "Contact Us", "Feedback", and so on. Can you discover these by searching? Would a two step-insertion make sense in the inserter (so first click is on "Form" and second is on one of the pre-arranged templates).

Interesting. I can mock that up to see how it feels. 👍

kjellr commented 5 years ago

For example, a "Form" block could have pre-defined sets using this new API for "Contact Us", "Feedback", and so on. Can you discover these by searching?

When there's a matching layout/pattern, a simple option would be to simply write out the template name underneath the block name. Then, if a user selects that item, we could serve up the matching template by default, and they could skip the layout-picking step:

Opt1-A

This still keeps it a one-step process when coming from a matching search.

Would a two step-insertion make sense in the inserter (so first click is on "Form" and second is on one of the pre-arranged templates).

One way to do this would be to swap out the entire panel to show the patterns after you select the main block:

2step-1

... or to have some sort of expanded drawer:

2step-2

Either of those two-step processes could also work well in the context of search, using the dark border to show the matching pattern result.

chrisvanpatten commented 5 years ago

Block transformations are already lossy, so in that sense I don't see layout transformations as that different.

I would challenge this a bit — when transforming a block to another type of block, I think the idea of data loss is intuitive and implicit. One block behaves differently from another block, with different properties and interfaces.

This feature is different: describing it as a 'template' implies that it's primarily a visual change, which will have little impact on the data of the block, just how it's visualized.

Now that said, @kjellr's examples in the above mocks are super interesting, and has me wondering… what if these patterns were simply treated in the block transform UI equally to any other transformations?

Really, what's the difference between transforming a block to another block and changing the 'pattern' of a block? To the end user, the effect is the same, and explaining the distinction between a block template/pattern and a separate block could be tricky, especially when the line is kind of fuzzy. A block pattern change that effectively resets the block (e.g. a change from 6 columns to 2 columns, which would likely lead to some major data loss) is hardly any different than changing a block anyway.

kjellr commented 5 years ago

Really, what's the difference between transforming a block to another block and changing the 'pattern' of a block? To the end user, the effect is the same, and explaining the distinction between a block template/pattern and a separate block could be tricky, especially when the line is kind of fuzzy. A block pattern change that effectively resets the block (e.g. a change from 6 columns to 2 columns, which would likely lead to some major data loss) is hardly any different than changing a block anyway.

Yes, this is an interesting point. I'm thinking this may rely a bit on the way these "patterns" are described to the user. If they're presented as "layouts", I wouldn't expect data loss. But if they're presented as different "types" of a block for instance, that might make sense.

One thing I'm repeatedly realizing is that some of these examples are relatively simple (a pattern that changes the column measurements of a Media & Text block for instance), while others are more broader structural changes (like the Form examples above). Even within the Columns block, there could theoretically be patterns that merely adjust the width of existing columns, and others that add or remove columns entirely. These sort of feel like they're the same thing, but the latter is much more consequential.

chrisvanpatten commented 5 years ago

One thing I'm repeatedly realizing is that some of these examples are relatively simple (a pattern that changes the column measurements of a Media & Text block for instance), while others are more broader structural changes (like the Form examples above).

The Form example is the one that jumped out at me as well. At a certain point, you get into a "Ship of Theseus" debate — if you're effectively rebuilding the block, is it really the same block?

jorgefilipecosta commented 5 years ago

Really important discussion happening here, full of awesome ideas ❤️ It seems we did not arrive yet on the UI to use, would having a branch with a prototype help make the decision in this phase or it is still too soon? If yes, any thoughts on the first approach to try?

mapk commented 5 years ago

Lot's of great work happening here! I love the consistent setup screen for the blocks.

To get a v1 implemented is a consistent way, I'm suggesting...

  1. Provide setup screen for blocks that will not lose content if the layout is changed (ie. Media+Text, Columns, Cover, Latest Posts). Yes, I believe we can get the Columns block to work this way.
  2. Layout options should be duplicated in the Block Inspector sidebar.
  3. For each of those blocks, I believe "Layout" works well for the term used.

When thinking about more complex blocks like a Form block, I believe the setup screen works best for selecting a "type" of form, keeping the Inserter free of these things. In these cases where a change of form would most likely cause a loss of content, it would be best to not include the different forms in the Inspector sidebar. If the user wants a different form, they would insert another Form block from the Inserter.

This begins to get a bit foggy for me though in terms of Style variations and Layouts. Style variations are found in the block's transform tool, while Layouts would be found in the sidebar. The separation makes sense symantically, but currently the transform tool offers layout variants as well. How would these resolve?

With this fogginess, I question whether other blocks would also follow this pattern? ie. Quote block, Gallery block, etc.

kjellr commented 5 years ago

To get a v1 implemented is a consistent way, I'm suggesting...

  1. Provide setup screen for blocks that will not lose content if the layout is changed (ie. Media+Text, Columns, Cover, Latest Posts). Yes, I believe we can get the Columns block to work this way.
  2. Layout options should be duplicated in the Block Inspector sidebar.
  3. For each of those blocks, I believe "Layout" works well for the term used.

This makes sense. All of these are fairly non-controversial, and it makes sense to display these options in both the placeholder and the sidebar.

This begins to get a bit foggy for me though in terms of Style variations and Layouts. Style variations are found in the block's transform tool, while Layouts would be found in the sidebar. The separation makes sense symantically, but currently the transform tool offers layout variants as well. How would these resolve?

One quick clarificaion: Block Styles actually appear in both the transform menu and the sidebar. I'm not sure how that effects our direction here.

mtias commented 5 years ago

@kjellr these two-step inserter interactions are interesting, I think there is something to it to continue exploring as it addresses the main issue of discoverability, which none of the in-block solutions do.

Let's not get too caught up in the data portability issues, these templates / layouts / patterns are always going to be changing attributes or inner block content. They are less useful as a transformation, and more useful as initial setup conditions, but can work in both. This is also the case with the larger full page templates we support for CPTs and such.

Columns always had this issue — if you switched from 4 columns down to 2, we need to make a decision on what happens with the content of the 3rd and 4th columns. The same applies to many other attributes you could set that depend on other attributes.

klihelp commented 5 years ago

Could be the data stored for until the edit page closed or the page save/update action? If deciding to restore the 4 columns before saving the page the lost data would be restored.

Columns always had this issue — if you switched from 4 columns down to 2, we need to make a decision on what happens with the content of the 3rd and 4th columns. The same applies to many other attributes you could set that depend on other attributes.

kjellr commented 5 years ago

I think some of the Form examples above pushed us a little too far into the weeds, and I'd ❤️ to get this moving again. Would it make sense to start building an MVP that works as @mapk described above?

Those blocks Mark mentioned have a clear need for this API right now, and seem like a generally strong place to start. Ideas like the two-step inserter seem like they can be explored after that core functionality is in place.

gziolo commented 4 years ago

I started working on the initial implementation. My plan is to have more iterations than discussed so we could rollout it quickly and start experimenting early. Potential steps:

  1. Create an API for registering patterns very close to block styles.
  2. Refactor Columns block to use this new API making the placeholder open for customization.
  3. Refactor more blocks that fit like:
    • Media+Text
    • Table
    • Cover
  4. Extract common logic as an initial screen for blocks that define patterns.
  5. Explore how it could be embedded in the block inspector.
  6. Explore how we can modify the search logic in the inserter to match blocks through layouts/patterns as proposed by @kjellr.

We can refine the list of tasks as we go. I just wanted to break it down into parts that are easier to implement, review and test.

mtias commented 4 years ago

It'd be very important first to clarify if what columns currently use fit within the same concept as block patterns.

gziolo commented 4 years ago

It'd be very important first to clarify if what columns currently use fit within the same concept as block patterns.

I think they do but the internal implementation will have to get updated slightly. I should push the API proposal soon.

gziolo commented 4 years ago

I opened #18270 which proposes the initial API for Block Patterns. It needs some polishing but it covers all the requirements. I used the Column block as a way to distill what's necessary. The implementation is based on Block Style Variations.

gziolo commented 4 years ago

I opened a continuation of #18270. It is based on the add/patterns-api branch. This PR refactors Columns block to use this new API making the placeholder open for customization 🕺 See #18283.

gziolo commented 4 years ago

Another experiment to integrate Patterns API with Media & Text block started in #18343

Screen Shot 2019-11-06 at 19 37 01

gziolo commented 4 years ago

Re-sharing my own comment from https://github.com/WordPress/gutenberg/pull/18343#issuecomment-551148834:

What I struggle with at the moment is that there is no formal way to detect whether the inserted block is in the mode where the user should pick the pattern. When you insert Media & Text it presents you some patterns to pick from, but when you pick one of them, save and reload, the pattern picker will show up again.

We discussed it with @aduth on WordPress Slack in #cored-editor channel (link requires registration): https://wordpress.slack.com/archives/C02QB2JS7/p1573132722147200

I was wondering whether there should be a formal way of detecting whether a given block is in the state where the placeholder should be presented to the user? I pointed out some ad-hoc solutions present in the codebase:

I also shared an example how we could take advantage of it for the Image block. When you insert such block, the following HTML invalid markup is included in the post content as long as it stays in the mode which shows placeholder in the editor:

<!-- wp:image -->
<figure class="wp-block-image"><img alt=""/></figure>
<!-- /wp:image -->

If we had a way to mark the block as one which still shows placeholder, we could easily filter it out from the content produced.

It raised the question from @aduth:

How can the framework be made aware of what those states are?

I described multiple ways of handling this placeholder state. One could be an attribute injected in the block definition, so the previous example for the Image block would produce:

<!-- wp:image { hasPlaceholder: true } -->
<!-- /wp:image -->

Another way is to offer a function that detects such state and is part of the Block API, it could use the logic similar to those you can see in the Columns or Table blocks.

@aduth also shared some interesting thoughts:

Personally, I think it might be fine if the block just output nothing when saving as a placeholder. So saving would be okay, but as long as it was <!-- wp:image /--> . The implementation just needs to be aware of what it considers as placeholder (an undefined url). And given that it seems accounting for this was overlooked even at this core block, understandable to be a problem for others, which can be an argument to formalize some placeholder status.

Finally, @mtias shared his point of view:

A placeholder is just a reflection — in the edit view of the block — of the current attribute state (generally the lack of attributes). It should never be an attribute in itself. Incidentally I was commenting this here: https://github.com/WordPress/gutenberg/pull/18363#discussion_r343694455

getdave commented 4 years ago

I have an additional use case that I'd like to open up for discussion / consideraiton regarding Patterns and InnerBlocks.

The new Nav Block requires a placeholder state. This is only to appear if there are no existing Blocks.

It will allow:

@mtias and I were discussing whether the above scenario is also a valid "Pattern" for the Nav Block or whether it's a more complex (and bespoke) UI interaction.

I've been looking at the UI states above and they are all locked into "select from X templates" so I can't see how this would work for the Nav Block use case as things stand.

mcsf commented 4 years ago

Thanks for the recap, @gziolo. I see two main approaches that could address this:

  1. Your relayed suggestion to look at the save output is interesting. Maybe there's something there: if a block type defines patterns, does it ever make sense for it to serialise as null? Likely not. In that case, by convention, a null output coming from a pattern-defining block is taken to represent an empty state.

  2. Another approach would be to look a block's attributes. Is any of its attributes that don't have a default value defined? If not, is the block in an empty state? A more thorough predicate would be:

    • none of its non-default-equipped attributes have defined values
    • none of its default-equipped values has a non-default value

Thoughts?

No. 1 seems delightfully simple, unless I'm naively forgetting other requirements.

mtias commented 4 years ago

A couple thoughts have taken better shape for me after these few months. There's currently too many similar but still distinct needs assumed in this API that we should untangle.

From these, the block patterns case is distinct enough that I think we should decouple it entirely from this API. Block Patterns would then be combinations of blocks (templates) with the aim of achieving a certain look or layout.

image

This example from @melchoyce is eloquent enough.

The Social Icons block has a different set of needs: we want to be able to maintain a single edit interface while being able to register different services as if they were their own blocks, so that it can be exposed within the child block inserter interface. For this case, the API would help reduce the overhead of having to register each as a new block, with all the tradeoffs therein (separate block types, overhead in deprecations, etc). Another case that might need this API is allowing a vertical as well as a horizontal version of the new Navigation Block.

These variations on a block should have the option of being exposed in a placeholder state or the inserter itself (and transforms, maybe even as special or prioritized transforms). Block patterns are from that perspective also a different breed — they are not exposed as blocks in the inserter because it's more important to represent them with previews than with icons.

Different layouts (the case of columns) is something that will almost always exist only in the placeholder state of the block (not exposed in the inserter as their own block types) while configurations should have that option (possibly also set by default, or enabled for search).

I think we could combine configurations and layout variations under the same API and exclude block patterns from it. Configurations and layout are fairly similar, and the few differences could be achieved expressively with the API (available in the inserter, available in placeholders, etc). I'd propose we call this variations or configurations to clearly separate it from block patterns.

mcsf commented 4 years ago

I think we could combine configurations and layout variations under the same API and exclude block patterns from it.

Thanks for the thoughts, I agree this seems like a good way forward.

Looking at configurations and layouts, are they to remain solely programmatic in the future? Because, if there is a scenario where users gain the ability to save their custom arrangements, some thought will need to be given to harmonising the concepts of block variations and reusable blocks.

variations or configurations

presets also came to my mind.

gziolo commented 4 years ago

A couple thoughts have taken better shape for me after these few months. There's currently too many similar but still distinct needs assumed in this API that we should untangle.

  • Providing different layouts for a block (the columns or media-text examples).
  • Registering different configurations or services (the case of embeds, social icons, etc).
  • Combining nested blocks in interesting ways (the block pattern directory case).
  • Expanding over style variations to behaviour.

From these, the block patterns case is distinct enough that I think we should decouple it entirely from this API. Block Patterns would then be combinations of blocks (templates) with the aim of achieving a certain look or layout.

It makes a lot of sense what you shared. It'd make it easier to discuss concepts as they are related. The block patterns looks like it defines the larger part of the content, so you could even think of it as a special version of the block which has hundreds of patterns registered. However, it should be easier to treat it as a completely independent API.

The Social Icons block has a different set of needs: we want to be able to maintain a single edit interface while being able to register different services as if they were their own blocks, so that it can be exposed within the child block inserter interface. For this case, the API would help reduce the overhead of having to register each as a new block, with all the tradeoffs therein (separate block types, overhead in deprecations, etc). Another case that might need this API is allowing a vertical as well as a horizontal version of the new Navigation Block.

Totally, this new API should give us more freedom to handle blocks that can have multiple versions but they behave the same on principle. I'm very positive that we can achieve this goal.

Different layouts (the case of columns) is something that will almost always exist only in the placeholder state of the block (not exposed in the inserter as their own block types) while configurations should have that option (possibly also set by default, or enabled for search).

I came to the same conclusions. That's why in #19243 I proposed scoping capability for the registered patterns (inserter vs block).

I think we could combine configurations and layout variations under the same API and exclude block patterns from it. Configurations and layout are fairly similar, and the few differences could be achieved expressively with the API (available in the inserter, available in placeholders, etc). I'd propose we call this variations or configurations to clearly separate it from block patterns.

I like the name variations more. It aligns with style variations which are an existing concept and as it turned out in my explorations you can use a pattern to change the default style variation applied when the blocks inserted. It might be confusing for some folks, but in general, it plays nicely if you think of variations as more flexible API which allows changing the block's state as well.

mcsf commented 4 years ago

17280 — Tracking this issue about Social Icons here because I expect that we can close it once Social Icons are based on ~patterns~ variants: the Inserter might be able to automatically do the right thing rather than require a new public prop.

gziolo commented 4 years ago

I updated the title and description to use variations rather than patterns as a name for this new API. I'm going to open a follow-up PR which updates all places in the code where patterns are in use to reflect that.

gziolo commented 4 years ago

19966 renames block patterns to variations as proposed by @mtias in #16283 (comment):

I think we could combine configurations and layout variations under the same API and exclude block patterns from it. Configurations and layout are fairly similar, and the few differences could be achieved expressively with the API (available in the inserter, available in placeholders, etc). I'd propose we call this variations or configurations to clearly separate it from block patterns.

We are approaching WordPress 5.4 beta and it's about time to evaluate if parts of this new API should be marked as stable. There two parts of the API that share the same methods and field in the block definition. Let me tackle them separately:

  1. There is a block variation picker that is integrated with the Columns block. It uses __experimentalBlockVariationPicker component to render variations that are fetched from the core/blocks store. I still seek for an ergonomic way to handle block variations picker case, at the moment it requires changes in edit implementation but I want to make it automatic, in the sense where you only define variations and the rest is handled for you. The biggest challenge is how to find a way in the block editor to preserve the information between independent sessions. Columns block has its own specific implementation that depends on the number of columns set – no columns means that picker needs to be displayed. I don't feel we have enough time to mark it as stable.
  2. There is also an integration of variations with the inserter. There is no native implementation so far but @mcsf is seeking a way to refactor Social Icons block (#17280) to use it. This is how it looks like in action with some custom examples: patterns-api-inserter-2 This part is very solid and addresses all comments raised so far. If we were able to land Social Icons block changes then I would be will confident that the API for the inserter bits is ready to be included in WordPress core.

Let me know what do you think.

mcsf commented 4 years ago
  1. It uses __experimentalBlockVariationPicker component […] I don't feel we have enough time to mark it as stable.

Agreed.

  1. There is also an integration of variations with the inserter. There is no native implementation so far but @mcsf is seeking a way to refactor Social Icons block (#17280) to use it. […] This part is very solid and addresses all comments raised so far. If we were able to land Social Icons block changes then I would be will confident that the API for the inserter bits is ready to be included in WordPress core.

I lost momentum this week (illness, other priorities), which is a shame. Would be great to pick up the pace on this and also explore Marcus's suggestion of turning Social Links into a variation of Navigation, figure out its viability.

gziolo commented 4 years ago

Now that #19887 is close to merging, I opened https://github.com/WordPress/gutenberg/pull/20068 to mark the API for the inserter as stable. It also will work with the Columns block.

__experimentalBlockVariationPicker remains experimental.

youknowriad commented 4 years ago

@gziolo Should we close this issue and continue in smaller ones if needed?

gziolo commented 4 years ago

@gziolo Should we close this issue and continue in smaller ones if needed?

We can handle it this way if you prefer 4 issues rather than one :)

Tasks left:

@mcsf and @mtias how do you feel about the follow-up tasks proposed?

mcsf commented 4 years ago

how do you feel about the follow-up tasks proposed?

They seem good.

The only other thing I see is exploring what kind of awareness the editor should have of blocks that are a variation, and how the editor would validate whether a block modified by the user still conforms to the variation or not. This exploration would be focused less on technical feasibility and more on identifying pitfalls and defining limits to how smart the editor should be about this. This is because I think there could be some interesting convenient applications for users, but this could also be opening the door for something quite messy.

mcsf commented 4 years ago

Do we need a label for Variations? I'm noticing comments such as this one on Make and other participants trying to get an overview of Variations development.

gziolo commented 4 years ago

Issues filed:

gziolo commented 4 years ago

Do we need a label for Variations? I'm noticing comments such as this one on Make and other participants trying to get an overview of Variations development.

On the one hand, it might be a good idea now that I created 5 new issues. One the other hand, I don't expect that there is going to be a huge number of issues opened in the future.

Let's close this issue and continue in follow-ups as discussed.

badfeather commented 3 years ago

Feature request: Open up block settings to the variations API. My primary use-case for the variations is creating custom variants of core blocks for use in themes or plugins. For ease of content editing, it would be very helpful to change the block category of the variation to the theme's category namespace, e.g.:

    wp.blocks.registerBlockVariation(
        'core/heading',
        [
            {
                name: '[namespace]-heading',
                title: 'Section Heading',
                attributes: {
                    className: 'section-title',
                    level: 2
                },
                settings: {
                    category: '[namespace]'
                }
            },
        ]
    );
gziolo commented 3 years ago

I don't see a category on the list of settings to override:

https://github.com/WordPress/gutenberg/blob/master/docs/designers-developers/developers/block-api/block-registration.md#variations-optional

https://github.com/WordPress/gutenberg/blob/90697bb776b4836f00f1837da0049d0579ab90b9/packages/blocks/src/api/registration.js#L77-L108

It is doable, I can't think of any blocker.

badfeather commented 3 years ago

A couple more questions/feature requests:

  1. For blocks that allow innerBlocks (columns, group), is there a way to specify an allowedBlocks attribute? If there isn't, this would be very useful.

  2. Can variations be nested in other variations? In other words, do they behave as standard blocks? And if so, how should they be referenced? Live via the variation name, or via the core name with some sort of variation attribute? If they can't, it would be great if they could!

I realize both of these questions fall somewhat into block patterns territory, but I'm looking for solutions that aren't pre-populated with content. Variations have the potential to be much more flexible.

gziolo commented 3 years ago

@badfeather, the use case with innerBlock enters a different territory. It internally leverages block templates as documented in: https://github.com/WordPress/gutenberg/blob/master/docs/designers-developers/developers/block-api/block-templates.md I'm not aware if you are able to define allowedBlocks through this API. I couldn't find anything like that in the docs for InnerBlocks that also defines template prop: https://github.com/WordPress/gutenberg/tree/master/packages/block-editor/src/components/inner-blocks#template

I agree it would be great if you could have more control over it 👍🏻 There is even an open PR that tries to introduce something similar for the Columns block: https://github.com/WordPress/gutenberg/pull/25778.