 All right, good morning, everyone. And welcome to the first English session of the day. Before we start, just a tiny gentle reminder that there are events taking place in the neighboring halls. So if you want to exit, please exit quietly, close the door quietly, and try to move through the other rooms without disturbing the other events. And for the first session of the day, we will be walking through some incredibly cool stuff we can do with the block editor presented to you by Fabian Caggy. A warm welcome. Good morning, everybody. And thank you for coming to the first talk of the day. I hope you very much enjoyed your day yesterday and the Contributor Day and are awake and ready for today's sessions. Brief introduction of myself. My name is Fabian. I've been working on slash with WordPress for the last 10 years or so. I currently work for the WordPress agency TenUp as an associate director of editorial engineering, meaning I do block editor stuff all day long. And today, I will be talking about extending the block editor. A couple of prerequisites for this talk. It does assume that you have a rough idea of foundational understanding of just the overall layout of the editor and some of the terms that are used in the editor, some of the areas. And also, all of the code examples that I'll be sharing, all of the JavaScript code examples, are assuming that you're using a modern build process, such as WordPress scripts or any Webpack-based or any modern build process to transform that JSX code. Before we actually dive into any of the things that I'm going to talk about, I'm going to save you all many headaches in your WordPress development life. With modern WordPress, there are more and more levels of caching that are happening because all of these JSON files and all of these pattern files are a little bit slow to load. And that is perfect for our production environments, but our local environments do not like that very much. And when we try to update something in theme JSON, for example, and it doesn't show up for half an hour, that's not great. So I do encourage all of you to enable the WP develop modes on your local environment to ensure that none of that caching slows you down while you're developing. From that, we're going to dive into the first section, which is theme JSON. And as you may all know, theme JSON allows us to configure settings, presets, and styles of our themes. So theme JSON is structured in a way where we have essentially a global section where we can configure all kinds of global stuff, and then we can also dive into per block or per element settings and styles. And with this, we can configure things like the default color palette, or it can configure whether or not somebody is allowed to use custom colors or all of those different things. Something to be aware of when working with theme JSON is that they're actually under the hood many different layers of theme JSON. So as you see in this diagram here, we have these four, or if you use a child theme, five different layers. That is, the specificity goes up the further down you go. So by default, we just have the default values of all of the theme JSON settings that are in core. That, if you have a block that defines some dials in the block JSON, those override the default from core. And then your theme JSON overrides all of those settings again. And the user settings that a user may choose in the global styles interface in the site editor, those again override all of the previous settings. And what's interesting is that for a couple of releases now, there are PHP filters to allow you to filter the settings and all of the different styles and everything in theme JSON at all of those different levels. So if you're developing a plugin that is trying to integrate something like Tailwind Styles into your block editor, for example, you could use one of the kind of lower level hooks to actually allow you to just make that available to everybody. But if you're working on a theme or on a child theme and want to override behavior, you may want to use one of the later hooks. And then if you want to ensure that filter just overruled all the things, you want to use the kind of user level and therefore force those settings because no other later setting can override them. There is one more filter that we got a couple of WordPress releases ago, which is a JavaScript filter that is the block editor use settings before hook. And that filter actually allows us to do one thing that all of the others don't, which is contextually aware changes of the settings. So in all of these filters, and I'll show some examples in a second, we only get information about the current request. So those that happen on the server, you don't know anything about where exactly that block is used, except maybe the current page or the current post type, whether a cookie is set or something like that. But with this setting, we actually get contextual information about whether a block is nested in another block or what the configurations of that block are. And so there's some really cool stuff we can do with that that I'll show in a second. Before we go to that, though, I want to show some examples for the PHP-based filters. So here, as you all know, when we have a heading block, for example, there are some color options that can be enabled or disabled using theme JSON. And by default, that is under the settings, color, we can enable and disable text background and link colors. And for example, we could use these filters to just disable them for all the users, first of all, to make sure, hey, nobody's allowed to change color. But then we can say, hey, if the current user is an administrator, if they have the ability kind of the user role permission to add theme options, then we're re-enabling that. And so we can have a different experience based on the user role of the user that is using the editor. Another example for actual front-end users here, we could use that same mechanism to check for the presence of a cookie in the current request and serve a dark mode or light mode of the theme JSON based on the filters here. Now, this is an example that uses the JavaScript-based filter. So here, we have a heading block that, again, has those color options. You can see them right here. And then when we switch to using that same heading block, paragraph block here, in a group block that has a dark background, we can disable those options, for example, which is super powerful. We have a lot of flexibility. We can do crazy things with it. But it should also be used with a lot of caution because we can create a very, very confusing experience when a block certainly behaves differently based on context. So a lot of power there, a lot of flexibility, but has to be used sparingly and with caution because it can create very unpleasant experiences. Here's the code example for that. And I'll just briefly talk about some of the things here. So we're hooking into the filter. We're getting the actual value of the setting. We're getting the name of the setting. And then we're getting the client ID and the name of the current block. And this filter runs for every single block in the editor all the time. And so using the client ID and those things, we can, for example, get all of the ancestors of that block, figure out whether it's in a group block, and then figure out whether that group block currently has a certain attribute. And then based on all of those contextual information that we now have, we can change. For example, right now, I'm just changing the Boolean value of whether colored.text is enabled or not enabled. And that's pretty much what's happening here. And I'll share these slides afterwards so if you're interested in the code. The next thing with the theme JSON that I briefly want to touch on is how we handle some responsive control. And that's especially important for things like topography spacing. And there are a couple of methods, even though there aren't any specific bright points in the theme JSON because WordPress very much believes in intrinsic design principles for that. There are still many things that we can do to make our variables responsive. First of all, whenever we're defining our presets, of course, as the value, use a clamp value, use custom CSS ourselves to make fluid type in this case. There also is fluid functionality baked into WordPress. So we can in our font sizes here define, hey, this actually is a fluid font size, and then we can define the minimum and the maximum value, and WordPress will automatically generate those clamp values for us. For many cases, when we have very strict design guidelines, though, that won't cut it. That just doesn't solve it. And so the approach that we're often using is we're actually, instead of setting a hard value for the actual font size, we're setting a CSS property, and then we're using our custom CSS to swap out the value based on the actual breakpoints. So we don't have a fluid type scale, but we actually have different values on fixed breakpoints. With that, I'm moving on from talking about theme JSON and going into patterns. I've ripped most of my patterns stuff out because Brigitte is going to cover a lot more of that later today, but I briefly want to say a couple of things. First of all, we can think of our blocks, kind of when we think about the atomic design principles, we can think of our blocks as the atoms, and then the patterns as kind of the molecules and organisms of the design system. And a rule for modern WordPress development, I would say is every single section of your design, every unique identifiable section of the design should be made available as a pattern because that is the easiest way to empower our editors, the users of the block editor to actually see what they're doing and to ensure already styled sections. They shouldn't have to go in and configure all of the blocks manually to get to a certain element, but rather just drop in a pattern that already has those things pre-configured and then they can customize it from there. Another thing by default, WordPress comes with the core pattern library. And I think that is a great and very valuable tool for many individual site owners, but when you have a very tightly defined design, those patterns just don't match the brand guidelines. And so they're cluttering up the experiences and kind of take away from all of the custom patterns that we're providing. So there is an easy theme support option that we can remove so the core pattern library doesn't show up in our custom builds. The final thing that I want to say about patterns is I'm often hearing people kind of refer to patterns as, hey, should I build a custom block or should I build a pattern? And I don't actually think that is a great kind of comparison. I think, of course, we have to choose whether or not we can implement a design using all of the core blocks or whether we want to build a custom block for it. But regardless of the tools that we use to build a design, anything should be packaged up as a pattern. So regardless of whether a pattern contains 20 different blocks combined together or whether it just combines one singular block, as long as it is a unique, identifiable section in the design, it should be packaged up as a pattern so it's easy to insert. Moving on, block walking. That umbrella term actually has a couple of cool features within it that I think are a little unutilized. So I'm going to briefly show you some of them. First of all, we have the ability to define a template lock on any of our inner block areas. And there are a couple of different options. You can see right here, we have a group that has some columns within that uses some images and just this entire design element here is the group. And right now this has no template lock applied to it. I could also set the template lock to insert, which it would still show up the same way. You could still move the individual blocks around in this pattern, but you couldn't insert any new additional blocks or you couldn't remove any of the existing ones that are already in here. The next mode we have is template lock all. And that means we can still configure all the options on all of the individual blocks within, but we can't remove any, we can't add any, and we also can't move them within this section. And then the final mode is the content only mode. And as you just see, when I swap back and forth here, the actual list layout over here changes because all of the blocks that don't actually contain content, so they're unlike the paragraph, the button or image and so forth, they disappear. They are not even showing up for the user anymore. And so we're hiding a lot of that complexity and only kind of showcasing the actual content that can be edited. And that can be super powerful when we have those patterns that contain a ton of different blocks to accomplish the design, but we don't actually want to expose all of that complexity to a user who may just care about changing the content. With this, when we're using the content only mode, I just showed you how it shows up for some of those core blocks. Whenever we're building a custom block where we also want some content to be editable in that mode, this is how it actually works under the hood. If we define an attribute and we tell the attribute, hey, this has the right now still experimental role of content, that means it now shows up in this content only mode. And some of the core blocks, like the group block, like the media text block, cover block that use inner blocks, actually allow us to define that template lock, which usually is defined on the inner block area itself has an attribute. So we can use this in our patterns. If we build a pattern with just the group block as a wrapper, we can apply this template only locking on that group block or that content only locking. And it applies that to the block. Another feature in this section is actual individual blocks allow us to lock them. And this actually is tied to the UI. So in the UI, when you click on the ellipsis menu in the block editor in the panel, you get this option to lock the blocks. And then you can lock movement and you can lock whether or not it can be moved. And the way this actually works is, again, it uses an attribute under the hood and this attribute gets registered for every single block in the block editor that happens from the editor itself. And what we can do because we now know how this works is we can actually change the default values. By default, all of these are false, but when we're, for example, building a custom header block that should be inserted on every page and just locked in place, we can set the defaults here to true. And now this block can't be moved and can't be removed anymore. But by default, you can still use the UI, same as I showed you a second ago, to unlock all of those properties. By setting these supports lock value to false, we can get rid of that entire locking UI. So by setting that value, and we can also filter that for other blocks, we can disallow editors to change the locking status of a block. A cool thing about this is we can also disallow the locking outright or again, based on the current user or based on user role. And so there is block editor settings all hook where we can set this settings can lock blocks. And we can, for example, allow it only for the editor role and above. We can, for example, only allow it for a specific user or we can allow it for pages and posts but not other post types. And so that really allows us to have fine control over who can lock and unlock things in the block editor. In WordPress 6.4, as of the release candidate right now, there is a new hook that also allows us to work with these editing modes. It's called use block editing mode and it has four different modes. It has the default mode. It has the content only mode that I already showed you. And the hook allows you to check in your block whether or not you are currently in this mode or you can also force your block into that mode using the hook. And there's this new disabled mode, which this is actually used under the hood in the page template preview where you see we have the header here present in the, it's loaded in the design but it's not showing up in the list view. And this disabled mode actually completely removes a block from, removes all of the block UI. There's no setting sidebar. There's no toolbar. It doesn't show up in the sidebar. The block is completely disabled. You can't interact with it at all but it still shows up visually, which is great if you wanna display template elements, if you wanna include things in the actual editor that are just visual elements to help a user understand the context for example, but it's not actually an element that may be rendered on the page. With that, I'm moving on to block extensions. And this actually, I found a great example for this when I looked at the beautiful new 2024 default theme. And when you look through the theme, you'll find that it uses this little asterisk on headings here that you can enable very easily. And the way this is built is it uses a block style. And a block style is a very, very simple API that is easy to use for anybody who... It's just super easy in PHP. You don't need to know any modern JavaScript. You don't need to know any React. You can just add additional block styles using this very simple function. And I think it is super cool and powerful API, though I have some issues with it. And I'll showcase an example of how this can get out of control on a project very quickly. So let's, for example, say, we do this on a client project and two weeks after we launched this, the client says, hey, I love this feature. I want to actually have a star and circle variant of it. And then we implement that. It's super easy. It's just three lines of code. And then a couple of weeks later, if they come back to us again, hey, I actually want to have a small and a large variant of all of those. And you're starting to see the issue here. The block styles are not composable at all. You can't choose multiple block styles at the same time. You can only ever choose one. So that scales kind of exponentially and we're very quickly run into bottlenecks. With this approach, if we're working on a site where we're continuously developing it and adding to it. So instead of using block styles for these types of things, and they certainly do have their place, but for these types of things, I much prefer extending blocks. And the way this could look here, for example, is instead of a block style, we could add an ornament section to the sidebar and allow you to turn them on, choose the ornament and choose the size. And if in the future, we choose, hey, we want to add 20 more items, it just show up in the ornament and or in this select dropdown, or we could build a more beautiful icon picker UI. If we want to allow you to change the color, we can add that into the section and it just scales with the demands that we have in the future. The way this actually works in the hood and bear with me for a second, there is an easier way coming. There is a lot of boilerplate that goes into this, but I'll still show you briefly how this actually works under the hood. So first of all, we need to add all of these additional attributes to the block. So we can define them here and just an object. And then we can use the blocks.register block type filter to actually add those additional attributes to the block registration in JavaScript right here. Then we actually same as if we were building a custom block, needs to actually build the controls for this. So we're building essentially our edit function, the only thing that is different, we don't need to produce output, we just need to use slot fills like the inspector controls or the block controls to actually render that output. And we can add that to the block using the editor.blockedit hook in JavaScript. And you can see here, we're just checking whether it's the block that we want to add it to. And then if the block is selected, we're rendering those additional settings, if not, we don't. And then another thing we need to handle is we still, the actual front end output of our block extension is no different to the output of a block style. We're still just outputting additional class names to the wrapper. So what we want to do here, we want to apply those same class names in the editor to the block element so that we have that rich preview in the editor. And the way we do this is again, another filter, the editor.blocklist block, and we can apply any inline styles, any class names, anything to that block element. And then finally, since we are working, we also want this to work with dynamic blocks, we do need to do some of those things again in PHP so that if we want to apply this style to the query loop, for example, this is needed for this asterisk here, but if we want to do that for dynamic blocks, we also need to do it in PHP. So we can again register the additional attributes to the block and we can add those additional class names using the HTML tag processor, which if you've not played with that, I would highly encourage you to do so. It is really powerful if you want to manipulate block content on the server. But as I already said, that is a lot of code. So a lot of the code that you actually saw in here is boilerplate that you can either easily abstract in your own helper function, or in the case of 10UP here, we have a small npm package called the 10UP block components that we bundle a function in that is called register block extension, where we can essentially just give it the new attributes, give it the actual edit function, and give it the class name generator, and that uses all of those hooks that I showed you under hood and produces the same output. So if you want to support dynamic blocks, you still have to do those two PHP things, but this is all the JavaScript code that you need to actually do the same thing that I just showed you before. With that, I have two brief more things that I wanted to talk about. One is the query loop block, which if you're working on a modern WordPress site, especially if you're looking into block-based themes, this is the replacement of the traditional WP query that we all are familiar with. And in this example here, I have a custom post type called team, and I have a taxonomy for the role, and I'm essentially replacing a design element that is already in 2024, but with a custom post type instead of just hard coding it in the content. But we can improve the experience of this for our users in a couple of different ways. One, we can actually create a block variation of this, and this allows our editors to quickly insert a block that already has all of those things configured. So for example here, this block variation shows up in the editor as if it were its own unique block. It already has those query parameters set, so we can tell it, hey, already choose the team post type and kind of pre-configure all of those things. But the query loop has some cool tricks up its sleeve. We can also specify the allowed controls. So the query block is a very confusing block for a lot of people who are new to the block editor because it has so many different options. And with the variation, we can actually get rid of most of those options here and only allow the ones that they need to be aware of for this variation. So in this team member block variation that we've created here, they don't need to change the post type of this. They don't need to change all of these controls. Those controls are just, we can restrict it to only those three for example, and the rest is completely hidden. And then one thing when you're building custom blocks, when you're working with a query loop, one superpower is building custom blocks that actually interface with the query loop. So if we go back to this example of the team member listing here, let's say we add custom meta value to all of our team members. And now we want to display that in the query loop here. The way that we can do that in our blocks is by using a system called context in the editor. And in our block JSON, in our block registration object, we can configure the context that we actually want to use. And in this case, we want to use the post ID and the post type. And then in our block edit function, we get the post ID and the post type passed in via context on the arguments. And then we can use that in our select call and our kind of data fetching. And the cool thing is, this context is, if you use it globally in a post, it just is the current post ID of the thing that you're editing. But as soon as you move that block into the query loop, it now is the post ID of the post that is displayed in the loop. And so this allows you to build custom blocks that work on the top level, but also interface with your query loop. One more quick tip when you're doing that, there actually is another thing that gets passed with context. And that is the query loop always gives you a context called query ID. And for example, if you've ever used the post title block, if you just use that in a post, you can edit the title. But if you use the post title block in a query loop, you can't edit that title. And the way that core figures that out, it checks for the presence of this query ID and checks whether it is a finite number. And if it's a finite number, we know, hey, we're within the query loop. And so this way you can check, hey, if it's in the query loop, just render the content. It's not editable. If it's not in the query loop, render the actual editable control. And that way we can make our custom blocks behave the same way as core blocks do. And with that, I think amount of time and hope you'll learn something. So do we have any questions for Fabian? If you have any questions, please raise your hand and I will come to you with a mic. Hi, my name is Cendric. Thank you for the presentation. I have one question regarding patterns and custom blocks. I know you said everything should be a pattern and I deeply agree with that. So where's the threshold for you in your work experience? When do you compose a type of design or a piece of design as a block pattern and when do you build a custom block? Where's that threshold? I would say the threshold, which I know this is not the perfect answer, it sadly depends. It depends on the client, it depends on the needs because the same design element, you can build not everything, but you can build a lot either as a custom block or just using all of the core blocks. If we think of a call to action, for example, that has just a piece of text and a button and a background, you could completely build this with a group block and just a button block and all of those, but that gives a lot of flexibility and a lot of freedoms to the user, which is great for some clients, but is not the right thing at all for other clients. And so for that reason, I think there isn't one just blank rule to say, hey, this is when you should always use just core blocks. This is when you should always use custom blocks. I do think the demand for simple custom blocks has gone down since we have that content only locking mode because if we have those clients that actually need that controls experiment or that control experience, we can build that same call to action as a pattern that uses content only locking and we pretty much have the same experiences if we had built a custom block. And so that, I think, is one of those design elements where we can do that. The content only locking with patterns is very, very powerful and does achieve a lot of those things. I will say I'm still a big proponent of building custom blocks for things where it makes sense. I'm not, for example, a fan of, if you build a pattern, a cool little trick that many people use is every block can get a class name designed to it. And just adding arbitrary class names that are not ties to controls in the block editor, but just that allow you to specifically target that element and just putting that into the pattern. And I'm not the biggest fan of that because it makes it completely opaque to the user why those settings now appear. Hey, why is this? This arrangement of group block with some headings completely different to this other arrangement of group blocks. And so whenever I need custom class names to target something, I wanna use block extensions to give editors controls to choose them. And then we can still use content only locking and remove all of that complexity if we want to need that. But that's a very long and not super straightforward answer, but... Just to make sure I understand that too. Your answer was if you need additional class names on your blocks so you can change styling and it propagates through already used patterns, then you use a custom block because patterns don't update styles when there is something. So if I have a pattern that has a black border and now I want a red border, only the future use of that pattern will have that red border or the black border and the others will still have the red border. Yeah, that also is something that really ties into the decision-making here. As we already just mentioned with patterns, a pattern is a concept that only exists up until the point where you insert it. At the point of insertion, a pattern ceases to exist and it just becomes the blocks that it was made out of. And so if you use any of the kind of design tools in WordPress to style your pattern and in the future want to make design updates to that and change the pattern, that doesn't have any effect on any already existing content created with a pattern and that can be a reason why choosing to build a custom block in some instances does make sense. It depends on what kinds of updates you want to do because you can also, if it's more broad design update, if you use kind of color, topography, spacing, the actual variables that are set up in ThemeJSON, if you, of course, update those variables in ThemeJSON, it propagates throughout the site and throughout all of the patterns and all of the content. So it very much depends on what types of updates we need to make and I'm very much hoping for partially synced patterns, the magic term that has been around forever to hopefully make its way into Gutenberg and then finally core at some point in the future because I think that will solve a lot of these problems when you can choose what needs to be synced and what doesn't. Relating to some of your hoping for, I would love to know what, gonna give you a magic wand. If you could have one thing, you can have a couple of things if you need. Because I think people will be like, oh, if only this existed in my workflow or only if this, what are you looking for to really help you? What are your stumbling points at the moment that you're hoping to have? Because I think sharing that helps kind of people as well. That is a very good question and I wish I had more things on the top of my mind right now. It may not be the thing you're expecting right now but one of the things that I personally would love to get is a feature that we now have in the site editor also applied to the post editor and that is the ability to preview the current template in a current post when you're editing it because one of the things that we're having to do a lot right now for custom builds to achieve that desired outcome of actual front end like experiences in the editor is when we have a hero, a header element that has a featured image and the title is overlaid on the featured image and we have the author and all of those things in there. Right now, if you look at the post editor, it looks nothing like that. And so what we do in a lot of cases is we build a custom header block where we actually build it using core blocks with a cover that uses the featured image and all of that and actually place those elements in the post content via a template that we define on the post type. And that is great because we get that full rich preview in the editor. The actual editor looks exactly like it does in front end. You have full confidence in your content editing abilities but it has the downsides that we're putting things that should really be part of the template into the individual posts. And so if we wanna have larger factors of the template in the future, that means it's just more difficult. And we can do so if we build it as a custom block because we can swap out the underlying HTML but if we're using core blocks, there really isn't a good way. And so that is something that if we... And the option is in the site editor already. The issue just is that the code base for the site editor and that post editor have diverged so much and there are so many compatibility modes in the post editor that right now that time is just not spent on it. The energy is being spent in other areas. But if I could just have that magic one, I would have the option to apply the template of the current thing that you're editing in the post editor itself. Sorry, one last thing. I've seen in the started presentation that you're also achieving some form of responsive break points stuff with piping CSS variables through with theme JSON. And for example, changing font sizes depending on the width of whatever. How do you make that opaque to the user? How do you communicate that that is happening to the user? Because we're doing that as well. Always feels kind of dirty. It always feels like you're not supposed to do that. And I think you aren't. But still it's often required. Yeah, I think that oftentimes starts with the design and how consistent we can be in a design. Because if from the very beginning of the design we have a type scale that actually scales properly and does not have many edge cases where it doesn't adhere to all of those, where it does adhere to that scale. Then I've not seen too many issues with it being opaque to the user because they have the confidence in the preview. Even if they use the responsive previews that it just looks right. They don't have to worry about it. They don't have to care about it too much. And once they can build that confidence in the system they often start caring less about it. The issue that we're also running into and it's not a completely solved problem when we can't give them that full confidence. When we can't give them the confidence that, hey, you just choose the font size that looks right to you in the editor and will make it work for you. If they aren't happy with the choices that are being made then it really becomes complex because there just isn't a great way. One of the things that I'm always doing in custom builds is I'm disallowing custom font sizes because those just don't scale responsibly. They just, if you choose something it may look right on desktop devices but it for sure won't do in mobile. So the only options that the editors have are the variables that we've given them. And those do get swapped out under the hood and those do scale. But besides that it oftentimes is something we start identifying those issues in the design process and are trying to be as consistent as possible so that we can build that trust and so that it does do the best work it can. We've not opted for actually giving responsive options in the editor kind of, you could use the block extensions to build your own custom responsive settings and allow them to change it based on viewport. We've not kind of, you've tried that, weren't happy with it and didn't stick with that approach because it just makes it too messy and too cluttered of an experience. But yeah, I certainly know the cases that you're describing where it is difficult. No more questions? We'll have a final one maybe. So in that case, thank you. Thank you Fabian. We have a small gift for you. And now we will have a small break and resume the talks at 11 o'clock. So make sure not to miss that.