-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
What problem does this address?
We want to be able to control what block settings are offered to the user in more ways than core currently allows.
I work in the space of building WordPress applications for enterprises and large organizations. For those of us in this space, this makes our end-user a bit different from the individual or small business that might benefit from granular design control over blocks.
Our users have the resources to hand theme design and development over to designers and developers. Our challenge isn't implementing a design in the block editor, but developing blocks that provide more targeted flexibility and options within an existing design system.
Our users aren't designing websites and themes in the block editor. They're assembling websites using blocks that have been designed and customized for them specifically. For the designers and developers making those blocks, governance is a primary concern.
Right now we can define block settings in theme.json like this.
As a simple example, let’s look at color.
Our global styles palette contains several color options. It looks like this:
"palette": [
{
"name": "Text",
"slug": "text",
"color": "var(--wp--custom--c--gray--70)"
},
{
"name": "Heading",
"slug": "heading",
"color": "var(--wp--custom--c--black)"
},
{
"name": "Background",
"slug": "background",
"color": "var(--wp--custom--c--gold--0)"
},
{
"name": "Background Secondary",
"slug": "background-secondary",
"color": "var(--wp--custom--c--gold--3)"
},
{
"name": "Primary",
"slug": "primary",
"color": "var(--wp--custom--c--gold--60)"
},
{
"name": "Secondary",
"slug": "secondary",
"color": "var(--wp--custom--c--gold--30)"
},
{
"name": "Link",
"slug": "link",
"color": "var(--wp--custom--c--gold--60)"
}
},
We use the global styles --wp--presets--color object as a “theme” which defines the standard style tokens that our blocks will look for. Colors are named semantically and draw from the tokens of our design system which is housed in the --wp--custom object for now—although we're working on being able to reference it from it's external npm package.
We want to continue to use global styles as a way to give semantic structure to our styles. It mirrors how we think of our application while we're designing it and it makes "re-theming" a lot easier. It gives us a set number of variables that a block needs to support in order to be styled properly by the theme.
However, we don’t want all these colors to be available wherever a user is presented with a palette. We only want certain colors to be available in specific places and the number of available options can be overwhelming in situations where only a couple of options would be appropriate.
Limiting block settings is currently possible on a theme-wide level. You can override the theme palette within a block like this:
"core/heading": {
"color": {
"palette": [
{
"name": "Heading",
"slug": "heading",
"color": "var(--wp--presets--color--heading)"
}
]
}
}
Here I’m overriding the palette to limit the colors available within the heading block to the “heading” option. If we had alternate heading colors we could also add those here. This makes blocks a lot easier to use, especially as they become more complex and designers need to consider how users will interact with them in the editor.
The trouble is that this only happens on a theme-wide level. We want to be able to define all possible options that a certain block supports and then narrow down what options are presented to a user in the block editor at any given time based on a few context-based factors:
Where is the block? what is its’ parent? what template is it in? what post type is it on? what block is immediately before and after it? etc.
These questions are ones we consider when designing and the answers to them can impact what options we make available to a user.
Who is interacting with it? what permissions does the user interacting with it have? are they a designer? are they just a copy editor?
This becomes clear with the example of type styles.
Similar to the global styles --wp--presets--color object we use the --wp--presets--font-sizes object as a theme and name the tokens semantically. Here are all the options we currently have in our type system.
"fontSizes": [
{
"slug": "neg4",
"size": "var(--wp--custom--fs--neg-4)",
"name": "neg4"
},
{
"slug": "neg3",
"size": "var(--wp--custom--fs--neg-3)",
"name": "neg3"
},
{
"slug": "neg2",
"size": "var(--wp--custom--fs--neg-2)",
"name": "neg2"
},
{
"slug": "body-1",
"size": ".875rem",
"name": "Body 1"
},
{
"slug": "body-2",
"size": "1rem",
"name": "Body 2"
},
{
"slug": "body-3",
"size": "1.125rem",
"name": "Body 3"
},
{
"slug": "body-4",
"size": "1.25rem",
"name": "Body 4"
},
{
"slug": "heading-02",
"size": "var(--wp--custom--fs--4)",
"name": "Heading 2"
},
{
"slug": "heading-03",
"size": "var(--wp--custom--fs--5)",
"name": "Heading 3"
},
{
"slug": "heading-04",
"size": "var(--wp--custom--fs--6)",
"name": "Heading 4"
},
{
"slug": "heading-05",
"size": "var(--wp--custom--fs--7)",
"name": "Heading 5"
},
{
"slug": "heading-06",
"size": "var(--wp--custom--fs--8)",
"name": "Heading 6"
},
{
"slug": "heading-07",
"size": "var(--wp--custom--fs--9)",
"name": "Heading 7"
},
{
"slug": "display",
"size": "var(--wp--custom--fs--10)",
"name": "Display"
}
],
There are a lot of them and all the text on the site is mapped to a font size here that corresponds to our design system. This is essential for us to be able to maintain control and consistency across all the various applications our type scale needs to serve.
Similar to color, we really don’t want to present all these options to a user every time they are asked to select a font size. Not only would it be overwhelming but it would present a lot of possibility for error and would force our user to either make a design decision or consult a style guide or a designer for help.
Going back to the example of our heading block, it potentially helps to narrow down the options on a theme level like this:
"core/heading": {
"typography": {
"fontSizes": [
{
"slug": "heading-02",
"size": "var(--wp--custom--fs--4)",
"name": "Heading 2"
},
{
"slug": "heading-03",
"size": "var(--wp--custom--fs--5)",
"name": "Heading 3"
},
{
"slug": "heading-04",
"size": "var(--wp--custom--fs--6)",
"name": "Heading 4"
},
{
"slug": "heading-05",
"size": "var(--wp--custom--fs--7)",
"name": "Heading 5"
},
{
"slug": "heading-06",
"size": "var(--wp--custom--fs--8)",
"name": "Heading 6"
},
{
"slug": "heading-07",
"size": "var(--wp--custom--fs--9)",
"name": "Heading 7"
},
{
"slug": "display",
"size": "var(--wp--custom--fs--10)",
"name": "Display"
}
]
}
}
Here, I’m limiting the options to only the heading font sizes. This is an improvement, but still falls short of the user experience we need. Giving a user all the heading options still forces them to make a design decision or consult a style guide or designer. If we could further limit the options here in a way that responds to the questions above we would be able to design a user experience that limits the possibility for design error—one that lets our users focus on content creation instead of design.
In our custom page-header block, our heading block is limited to 3 size options. Right now we accomplish this by forgoing the core block and making that block totally custom. This has achieved the experience we need for our users but it comes at the expense of introducing complexity to our codebase and opting simple blocks out of any further improvements that come through core.
What is your proposed solution?
Being able to pass a second set of settings for a block that only applies to a specified context would probably do what we need. Doing this in theme.json would be nice.
The theme.json settings for an implementation using core blocks might look something like this:
These are all the font-size options available to the heading block across the theme:
"core/heading": {
"typography": {
"fontSizes": [
{
"slug": "heading-02",
"size": "var(--wp--custom--fs--4)",
"name": "Heading 2"
},
{
"slug": "heading-03",
"size": "var(--wp--custom--fs--5)",
"name": "Heading 3"
},
{
"slug": "heading-04",
"size": "var(--wp--custom--fs--6)",
"name": "Heading 4"
},
{
"slug": "heading-05",
"size": "var(--wp--custom--fs--7)",
"name": "Heading 5"
},
{
"slug": "heading-06",
"size": "var(--wp--custom--fs--8)",
"name": "Heading 6"
},
{
"slug": "heading-07",
"size": "var(--wp--custom--fs--9)",
"name": "Heading 7"
},
{
"slug": "display",
"size": "var(--wp--custom--fs--10)",
"name": "Display"
}
]
}
}
This would be the curated sub-set of font-size options available to the heading block when it is placed within the page-header block:
page-header/heading {
"typography": {
"fontSizes": [
{
"slug": "heading-03",
"size": "var(--wp--custom--fs--5)",
"name": "Heading 3"
},
{
"slug": "heading-04",
"size": "var(--wp--custom--fs--6)",
"name": "Heading 4"
},
{
"slug": "heading-05",
"size": "var(--wp--custom--fs--7)",
"name": "Heading 5"
},
]
}
}