WordPress / gutenberg

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

Global Styles and Theme.json: Next Steps #62686

Open youknowriad opened 2 months ago

youknowriad commented 2 months ago

The Global Styles architecture and features is growing significantly and the complexity of both the implementation and the mental model is increasing due to the organic nature of the iteration process. It is a good time though to take a step back, take a look at the main issues we're having and how to address them while simplifying the mental model.

Currently supported features:

  1. Themes provide a theme.json (styles an settings) file that contain what I'm going to call a style variation. It defines colors, typography, palettes ... for the active theme.
  2. The default "style variation" can be edited in the UI and saved in the wp_global_styles CPT in a single entry (per theme).
  3. Themes can also provide alternative "style variations" for their themes, by creating new files under the styles folder like styles/red.json or styles/blue.json
  4. These variations are not editable in the UI but instead, you can actually copy their content and apply it to your theme in the the default CPT entry for the theme.
  5. In 6.2, we introduced the possibility to edit "block style variations" in the UI. So for instance a user can edit the "outline" style variation of a button (apply colors, typography...) and save this in the CPT entry under styles.blocks.core/button.variations.outline. In a way we're using the same theme.json structure and same global styles UI to edit a style variation that applies only to a given block.
  6. In 6.6, we're introducing a way to register these style variations that apply to one or multiple block types using files in styles folder and by using the top level blockTypes property to choose which block type they apply to. The structure is very similar to any style variation (default theme.json, red.json or blue.json)
  7. 6.6 also offers a way to register the exact same block specific style variations as nested keys (instead of separate files) in theme.json file (or red.json, blue.json) under blocks.styles.variations. The advantage here is that theme authors can define these variations within a parent theme style variation red.json file, so when the user picks the "red" style variation for his theme in the UI, it also changes the styles of the available style variations for the blocks.
  8. The block specific style variations registered using the method in 6 or 7 are editable in the UI just like the default block styles variations (see 5) and the changes are saved similarly.

These are great features, but it's easy to see how the multiple ways to write and save these variations can start to become confusing for users, in addition to the complex mental model, here are some issues that were raised before related to this model and some that are more hypothetic issues and features that we'd want to support:

A potential path forward / proposal

I think there's an opportunity to simplify the mental modal and solve all of the issues above:

Downside

This proposal mean that the configuration introduce in 6.6 under styles.blocks.variations is not ideal (as it breaks this mental model and becomes redundant) and might get deprecated later. Given how late we're in the release cycle of 6.6, I'm proposing that we deemphasize this feature (not remove it) in the docs / dev notes / theme.json schema... We can introduce a new apiVersion if needed to completely remove it.

I'd appreciate any thoughts on this proposal. Thanks. @aaronrobertshaw @ellatrix @carolinan @richtabor @andrewserong @ndiego @mtias @ramonjd @jasmussen @oandregal @tellthemachines

justintadlock commented 2 months ago

6.6 also offers a way to register the exact same block specific style variations as nested keys (instead of separate files) in theme.json file (or red.json, blue.json) under blocks.styles.variations. The advantage here is that theme authors can define these variations within a parent theme style variation red.json file, so when the user picks the "red" style variation for his theme in the UI, it also changes the styles of the available style variations for the blocks.

This proposal mean that the configuration introduce in 6.6 under styles.blocks.variations is not ideal (as it breaks this mental model and becomes redundant) and might get deprecated later. Given how late we're in the release cycle of 6.6, I'm proposing that we deemphasize this feature (not remove it) in the docs / dev notes / theme.json schema

The big advantage for theme authors with this method is that you can define a default block style variation in example.json. Then, you can use the blocks.styles.variations.example key to override it in your in your individual global style variation JSON files.

This is the primary use case for me, and solves some years-old issues that have needed very hacky workarounds. It's one of the most exciting aspects of the updates for 6.6.

For example, here's my section-1.json block style variation:

{
    "$schema": "https://schemas.wp.org/trunk/theme.json",
    "version": 3,
    "title": "Section 1",
    "slug": "section-1",
    "blockTypes": [ "core/group" ],
    "styles": {
        "color": {
            "background": "var:preset|color|primary-700",
            "text": "var:preset|color|white"
        }
    }
}

But this must look different in my various global style variations, and here is an example of overwriting section-1 in my global example.json file:

{
    "$schema": "https://schemas.wp.org/trunk/theme.json",
    "version": 3,
    "title": "Example",
    "settings": {
        "blocks": {
            "variations": {
                "section-1": {
                    "blockTypes": [ "core/group" ],
                    "color": {
                        "background": "var:preset|color|primary-900"
                    }
                }
            }
        }
    }
}

And each of my 9 global style variations add their own tweaks to section-1.

Style variations can have "metadata" to define where they can be applied: they can have a "blockTypes" config to define if they're global (omitting the key) or apply to specific block types. They can also have a "parent" key to define whether they are style variations that are only available in the UI when you switch your theme to a given style variation. (Addresses the use-case mentioned in 7)

Assuming I'm understanding this proposal correctly:

For me, this would mean I'd need to have even more JSON files to cover the use cases. Suddenly, my theme could go from its current 11 block style variation JSON files to 99 (that's 11 block style variations x their customizations for my 9 global style variations). That could potentially feel unmanageable.

I like the idea overall, and I feel like I could build a new organizational system to handle that. But I'd want us to think through the impact such a change might have. We need to see how this is implemented in the wild before jumping too far down another path. I'd argue that we'll likely want to maintain both methods.


I really like the idea of a parent key here to apply specific variations to a parent global style variation. For example, it's already come up in a conversation to be able to include specific color and typography variations into specific global style variations.

youknowriad commented 2 months ago

The big advantage for theme authors with this method is that you can define a default block style variation in example.json. Then, you can use the blocks.styles.variations.example key to override it in your in your individual global style variation JSON files.

Yes, this is solved by the "parent" key basically. You'll just register "section-1" multiple times with different "parent" keys. It does have the potential to increase the number of theme.json files but I feel like overall it's a better model and would be better than a huge theme.json with everything and every style variation override. The general idea is not incompatible with keeping these overrides, what I don't like principally is that today it's not just "overrides", they also register the variations. So things like styles.blocks.variations.myVariation work very differently from styles.blocks.core/group/myVariation. I would have preferred to use styles.variations.myVariation instead which would serve as an override just like styles.blocks.core/group/myVariation does and not as an override + registration.

ndiego commented 2 months ago

The more we can simplify the mental model, the better. It's definitely starting to get overwhelming.

This proposal mean that the configuration introduce in 6.6 under styles.blocks.variations is not ideal (as it breaks this mental model and becomes redundant) and might get deprecated later. Given how late we're in the release cycle of 6.6, I'm proposing that we deemphasize this feature (not remove it) in the docs / dev notes / theme.json schema... We can introduce a new apiVersion if needed to completely remove it.

The timing of this downside is unfortunate. I don't have any strong opinions, but if it means improving the architecture of theme.json in the long run, I'm for it.

ramonjd commented 2 months ago

Thanks for getting the discussion started. ❤️

Sorry for all the repetition below, I'm just writing things out so I understand the model.

You can switch the active theme style variation of your theme, which actually changes the "id" of the CPT entry used in the frontend.

As you've noted, the custom post type (CPT) wp_global_styles currently stores user styles for a specific theme. I'll call this the "default" CPT.

Currently, if a user selects a non-default style variation in the site editor, that variation's styles will be stored in the default CPT. The incoming styles are merged with any existing user styles.

WordPress doesn't know whether a style variation has been applied.

This default CPT represents the actual state of the site's styles.

Under the proposal, let's say a user applies a non-default style variation (example-variation.json). Right now, the data would be merged with the default CPT's data.

Now the user edits example-variation.json in the editor, and it's saved in a separate CPT with a parent key.

Questions:

  1. If a non-default variation is active/has been applied, should any updates to that variation be automatically merged into the parent default CPT as well? The consequence is that it could override any corresponding user-defined styles. That's currently the case right now anyway.
  2. Should the variation's styles remain separate, and not be merged with the user styles in the default CPT? They could be rather output as CSS separately according to an inheritance hierarchy. See: https://github.com/WordPress/gutenberg/issues/62661

1 file under styles in a theme = a style variation = 1 separate CPT entry: this means that style variations are not all saved to the same default CPT entry. You can easily create/edit separate style variations.

Presumably the non-default style variation CPTs can also be "reset". Each of these would generate a revision post when edited.

I know it's premature to discuss this, however I would say, therefore, that it would be useful to open up revision history for variations as well.

If that happens, the above questions are also relevant, but in the case where a user restores or resets a non-default style variation that is currently active/applied.

It also opens the door to enable "page specific" active style variation or "template specific" active style variations

For this idea, but more in general I like the concept of a visual representation or some other UI to explain to the user where styles are coming from, and where to edit them.

Especially so if style variations add another CSS layer to the hierarchy.

I'm thinking of the scenario in which a user asks, for example, "Why is this element blue? Where is it coming from and can I change it?"

See:

youknowriad commented 2 months ago

If a non-default variation is active/has been applied, should any updates to that variation be automatically merged into the parent default CPT as well? The consequence is that it could override any corresponding user-defined styles. That's currently the case right now anyway.

No, there are two separate actions:

These two actions are separately. We may offer in the UI "copy styles from variation into the active one" but that seems additional and not mandatory in the UX flows.

Should the variation's styles remain separate, and not be merged with the user styles in the default CPT?

Good question and an implementation detail that I can't answer right now, the important thing is that if you fetch a variation using the REST API or a PHP API (to generate the styles), you get the full object.

I know it's premature to discuss this, however I would say, therefore, that it would be useful to open up revision history for variations as well.

Yep, sounds great.

Especially so if style variations add another CSS layer to the hierarchy.

In the current proposal, I'm actually not proposing another level in the hierarchy, I'm simplifying to say, for a page or template, the user just selects a variation to act as the "active" variation (so the default one is not used at all, only the active one instead). I think it allows for the same use-cases without added complexity. But we may be getting ahead of ourselves.


If I were to start implementing the proposal above today, I'll probably start by implementing the mechanics to "switch active variations" and the save behavior. After that, I'll probably implement a way for users to create and edit variations in the UI. Later, we can think about these new possibilities (revisions, page level variations...)