Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose presets declared via add_theme_support in global styles #22076

Merged
merged 4 commits into from
May 6, 2020

Conversation

oandregal
Copy link
Member

@oandregal oandregal commented May 4, 2020

This PR exposes theme supported style presets (colors, gradients, font-sizes) declared via add_theme_support (see) in global styles so they can be used by themes directly in the theme.json.

Example

Input from theme.json:

{
    "color": {
        "background": "var(--wp--preset--color--secondary)",
        "text": "var(--wp--preset--color--primary)"
    },
    "typography": {
        "line-height": "calc(1.4 * var(--wp--preset--font-size--small))"
    }
}

Input from declared theme support via functions.php:

add_theme_support( 'editor-color-palette', array(
    array(
        'name'  => __( 'Primary', 'global-styles' ),
        'slug'  => 'primary',
        'color' => '#0073AA',
    ),
    array(
        'name'  => __( 'Secondary', 'global-styles' ),
        'slug'  => 'secondary',
        'color' => '#005177',
    ),
) );

add_theme_support( 'editor-gradient-presets', array(
    array(
        'name'     => __( 'Vivid cyan blue to vivid purple', 'global-styles' ),
        'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
        'slug'     => 'vivid-cyan-blue-to-vivid-purple'
    ),
    array(
        'name'     => __( 'Vivid green cyan to vivid cyan blue', 'global-styles' ),
        'gradient' => 'linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)',
        'slug'     =>  'vivid-green-cyan-to-vivid-cyan-blue',
    ),
) );

add_theme_support( 'editor-font-sizes', array(
    array(
        'name' => __( 'Small', 'global-styles' ),
        'size' => 12,
        'slug' => 'small'
    ),
    array(
        'name' => __( 'Huge', 'global-styles' ),
        'size' => 50,
        'slug' => 'huge'
    )
) );

Output:

:root {
    --wp--color--background: var(--wp--preset--color--secondary);
    --wp--color--text: var(--wp--preset--color--primary);
    --wp--typography--line-height: calc(1.4 * var(--wp--preset--font-size--small));
    --wp--preset--color--primary: #0073AA;
    --wp--preset--color--secondary: #005177;
    --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);
    --wp--preset--gradient--vivid-green-cyan-to-vivid-cyan-blue: linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%);
    --wp--preset--font-size--small: 12;
    --wp--preset--font-size--huge: 50;
}

Considerations

  • Each preset value is converted to a CSS custom property whose prefix is --wp--preset--[feature]--[slug]. Examples: --wp--preset--color-primary, --wp--preset--font-size--small, etc.

  • In the future, we may be able to declare these presets directly in the theme.json. While we get there, this brings us a ready-to-use solution that theme authors can count on. It may be the case that, even if we are able to declare presets via theme.json, we may want to support the previous configuration mechanism.

Testing

  • Download, install, and activate this testing theme (or create your own).
  • Enable the FSE experiment and visit the Site Editor.
  • Make sure the embedded stylesheet with ID global-styles-inline-css has the proper CSS custom properties (if the testing theme was used, it should have the same contents as in the example section above).

@oandregal oandregal requested a review from TimothyBJacobs as a code owner May 4, 2020 12:32
@oandregal oandregal self-assigned this May 4, 2020
@oandregal oandregal added the Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json label May 4, 2020
@github-actions
Copy link

github-actions bot commented May 4, 2020

Size Change: +491 B (0%)

Total Size: 822 kB

Filename Size Change
build/block-editor/index.js 101 kB +14 B (0%)
build/block-library/index.js 115 kB +460 B (0%)
build/edit-navigation/index.js 4.07 kB +17 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.02 kB 0 B
build/annotations/index.js 3.62 kB 0 B
build/api-fetch/index.js 4.08 kB 0 B
build/autop/index.js 2.82 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/index.js 6.6 kB 0 B
build/block-directory/style-rtl.css 760 B 0 B
build/block-directory/style.css 761 B 0 B
build/block-editor/style-rtl.css 10.2 kB 0 B
build/block-editor/style.css 10.2 kB 0 B
build/block-library/editor-rtl.css 7.08 kB 0 B
build/block-library/editor.css 7.08 kB 0 B
build/block-library/style-rtl.css 7.24 kB 0 B
build/block-library/style.css 7.25 kB 0 B
build/block-library/theme-rtl.css 683 B 0 B
build/block-library/theme.css 685 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/blocks/index.js 48.1 kB 0 B
build/components/index.js 179 kB 0 B
build/components/style-rtl.css 16.9 kB 0 B
build/components/style.css 16.9 kB 0 B
build/compose/index.js 6.66 kB 0 B
build/core-data/index.js 11.4 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/data/index.js 8.44 kB 0 B
build/date/index.js 5.47 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 3.1 kB 0 B
build/edit-navigation/style-rtl.css 485 B 0 B
build/edit-navigation/style.css 485 B 0 B
build/edit-post/index.js 28.1 kB 0 B
build/edit-post/style-rtl.css 12.2 kB 0 B
build/edit-post/style.css 12.2 kB 0 B
build/edit-site/index.js 12.3 kB 0 B
build/edit-site/style-rtl.css 5.19 kB 0 B
build/edit-site/style.css 5.2 kB 0 B
build/edit-widgets/index.js 8.37 kB 0 B
build/edit-widgets/style-rtl.css 4.68 kB 0 B
build/edit-widgets/style.css 4.68 kB 0 B
build/editor/editor-styles-rtl.css 428 B 0 B
build/editor/editor-styles.css 431 B 0 B
build/editor/index.js 44.3 kB 0 B
build/editor/style-rtl.css 5.07 kB 0 B
build/editor/style.css 5.08 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 734 B 0 B
build/format-library/index.js 7.63 kB 0 B
build/format-library/style-rtl.css 502 B 0 B
build/format-library/style.css 502 B 0 B
build/hooks/index.js 2.13 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 710 B 0 B
build/keyboard-shortcuts/index.js 2.51 kB 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/index.js 3.13 kB 0 B
build/list-reusable-blocks/style-rtl.css 226 B 0 B
build/list-reusable-blocks/style.css 226 B 0 B
build/media-utils/index.js 5.29 kB 0 B
build/notices/index.js 1.79 kB 0 B
build/nux/index.js 3.4 kB 0 B
build/nux/style-rtl.css 616 B 0 B
build/nux/style.css 613 B 0 B
build/plugins/index.js 2.56 kB 0 B
build/primitives/index.js 1.5 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/rich-text/index.js 14.8 kB 0 B
build/server-side-render/index.js 2.67 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.28 kB 0 B
build/url/index.js 4.02 kB 0 B
build/viewport/index.js 1.84 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.18 kB 0 B

compressed-size-action

@youknowriad
Copy link
Contributor

How does this compare to @jorgefilipecosta's PR where he tries to use CSS vars for these presets too?

@oandregal
Copy link
Member Author

You mean #21490, right? This PR is complementary in that it addresses the global level while 21490 works at the local level. It's also an enabler for 21490 as it may unblock some things that prevent 21490 from landing. I meant to comment there but it'll have to wait a few hours until I'm back from lunch.

@oandregal
Copy link
Member Author

I've just stumbled upon #20588 and come to realize the whole role of theme.json to control the editor, not only for global styles. It didn't coalesce fully until now for me.

With this newly gained knowledge, I'm thinking what prefix should we use for the presets: palette is too tied to colors, and theme is only one source of data we may have for presets (we may also have core presets and user modifications on top). What if we used --wp--preset--[feature]--[slug] instead? So we'd have --wp--preset--color--primary, --wp--preset-font-size--normal, etc?

I may want to propose that these are taken off from the config key suggested at #20588 (comment) as well as other few minor changes, but I guess that conversation is best decoupled from here and we should have it in #21490 instead.

@youknowriad
Copy link
Contributor

@nosolosw Here's the last proposal in terms of theme.json format #21583 (comment)

I may want to propose that these are taken off from the config key

Can you clarify this?

@oandregal
Copy link
Member Author

oandregal commented May 5, 2020

I'm still reading up other PRs that landed recently, but I was thinking of something along the lines of this for the theme.json (for completeness I also share other minor tweaks):

{
    "global": { /* same */ },
    "blocks": { /* same */ }, 
    "presets": { /* This would be made a top-level key out of the original config */ 
        global: {
            colors: [
                {
                    'name'  => __( 'Primary', 'theme-domain' ),
                    'slug'  => 'primary',
                    'color' => '#0073AA',
                },
                /* more colors */
            ],
            gradients: [
                {
                    'name'  => __( 'Primary', 'theme-domain' ),
                    'slug'  => 'secondary',
                    'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)',
                },
                /* more gradients */
            ],
            font-sizes: [
                {
                    'name' => __( 'Normal', 'theme-domain' ),
                    'slug' => 'normal'
                    'size' => 16,
                },
                /* more font sizes */
            ],
        }
        blocks: { /* along the lines of the general presets but per block */
            "core/paragraph": { ... }
        },
    },
    "editor": {
        "global": {
            "allowCustomColors": true,
            "allowCustomGradients": true
            "allowCustomFontSize": true,
            "allowDropCap": true
        },
        "blocks": {
            "core/paragraph": { /* along the lines of global, but per block */ },
        }
    },
    "theme": { /* potentially some theme supports that aren't related to the editor */ }
    "ui": { /*I don't understand the use of this key */ }
}

The reason is that presets should both configure the editor and generate CSS declarations (using custom or normal properties, that's not important atm).

@oandregal
Copy link
Member Author

oandregal commented May 5, 2020

Thinking out loud a bit: another thought that I have is whether the top-level "global", "blocks" and "presets" should coalesce under a single key called "styles" (which is what they do => generate styles). Example:

{
    "styles": {
        "global": {
            "color": "var( --my-palette-color-one )",
            "background": "var( --my-palette-color-two)",
            "font-size": "var( --my-font-size)",
            "colors": [ ... ],
            "gradients": [ ... ],
            "font-sizes": [ ... ],
        },
        "blocks": { ... },
    },
    /* other things */
}

If this made sense, the prefix for the generated variable could be actually none (what Jorge used in #21490): --wp--colors--primary, --wp--font-sizes--normal, etc.

@youknowriad
Copy link
Contributor

I don't think "palettes" or "presets" should be merged with "styles" because. The styles do generate CSS but the presets don't, the presets just generates CSS variables definitions which if not applied to any other style/selector won't do anything.

For me "presets" are more "config" of the editor/frontend so they are more related to enabling/disabling things. Also noting that passing an empty palette actually disables the UI in the editor.

All these three categories: "styles", "config" and "presets" can be "global" or "per block".

That's the thinking behind the proposal.

I can see how there's some similarity between "palettes" and "styles" but I think this technical similarity is more an "implementation detail" and not a conceptual one. (one configures the editor and one actually applies a style).

--

There's also a third category I called "ui" on that proposal which is in fact the UI exposed on the global styles panel.

@oandregal
Copy link
Member Author

I see how that logic also makes sense, I can be on board with that as well. So, to move this PR forward: would it be a fair assessment to say that we can go with the --wp--preset prefix for the variables we generate for presets and that a different PR will decide whether we bundle them in config or do something differently?

@youknowriad
Copy link
Contributor

So, to move this PR forward: would it be a fair assessment to say that we can go with the --wp--preset prefix for the variables we generate for presets and that a different PR will decide whether we bundle them in config or do something differently?

yes, that prefix is good for me 👍

@oandregal oandregal force-pushed the add/theme-support-to-global-styles branch from 3cf7e98 to 953c3d2 Compare May 5, 2020 17:51
@oandregal oandregal changed the title Expose theme supported presets via global styles Expose presets declared via add_theme_support in global styles May 5, 2020
@oandregal
Copy link
Member Author

OK, pushed the changes here and to the theme for testing and also updated the issue description. This is ready for review.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question for later: I wonder if we should have a "php script" that generates the stylesheet and gets enqueued into the editor and frontend for these.

@oandregal
Copy link
Member Author

question for later: I wonder if we should have a "php script" that generates the stylesheet and gets enqueued into the editor and frontend for these.

Can you expand on this? At first sight, I'd think global-styles.php is such a script, although it also does other things (register the CPT for user data, etc).

@youknowriad
Copy link
Contributor

Can you expand on this? At first sight, I'd think global-styles.php is such a script, although it also does other things (register the CPT for user data, etc).

i mean a php script that returns CSS, not something loaaded by other php scripts that render HTML.

basically something you could use this way:

<link href="global-styles.php" rel="stylesheet">

@oandregal oandregal merged commit 1b649a7 into master May 6, 2020
@oandregal oandregal deleted the add/theme-support-to-global-styles branch May 6, 2020 13:27
@github-actions github-actions bot added this to the Gutenberg 8.1 milestone May 6, 2020
@jorgefilipecosta
Copy link
Member

Hi @youknowriad, @nosolosw, Having a PHP script to load the global styles presents a big advantage we may allow browsers to cache global styles related to CSS variables, instead of sending them on every page load as inline styles. But there is a significant disadvantage for first-time visitors, or when the cache is invalidated, we may need to load the WordPress engine two times. The first time to generate the HTML and the second time to create global style variables. Users can customize them, so we need to query the database if we use the standard WordPress functions we instantiate another WordPress engine), I guess loading the engine two times has some impact.

@youknowriad
Copy link
Contributor

we may need to load the WordPress engine two times

There's no need to load the whole WordPress "engine" on that script, we only need to load theme.json and any function/file used to generate the CSS.

gutenberg_experimental_global_styles_get_from_file(
locate_template( 'experimental-theme.json' )
),
$theme_supports
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess $theme_supports should be before gutenberg_experimental_global_styles_get_from_file to give more priority to theme.json in case it uses theme supports and theme.json at the same time.

Copy link
Member Author

@oandregal oandregal May 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this was intentional, I tried to capture why in the comment before the return statement: essentially, there's yet a few options to store the presets in the theme.json and I didn't want people to start using something like this in theme.json:

{
  // global styles stuff
  "presets": { /* this data would be processed */ }
}

Which brings me to a different question: at the moment, we don't validate that the keys in theme.json are valid or follow the schema we expect (global, blocks, etc), so anything that theme authors put there will be converted to variables as well. I think this is fine for this stage and I even add some validation in some of the PRs I have somewhere. However, I'm on the fence if this is a good or a bad thing: in a way, having that freedom could enable theme authors to use it creatively (custom CSS). Do you have any thoughts about that?

@oandregal
Copy link
Member Author

Having a PHP script to load the global styles presents a big advantage we may allow browsers to cache global styles related to CSS variables

Coincidentally, a few days ago, I've just stumbled upon an experiment by Jorge about a similar problem: how to make the editor-styles a stylesheet so it's cacheable. In that case, we couldn't do it because of how some hosts rearrange and bundle the CSS stylesheets to serve them from CDNs. I was wondering whether that's something that will be applicable to the generated CSS from theme.json as well. If we start adding more rulesets with selectors that target blocks we may need adding the editor wrapper as well (hence, we're in the same position and can't add this as a stylesheet).

Another thought that I had was about hosts rewriting or not allowing certain URL paths to be reached (for example, *.php). I don't know a lot about this to be certain, but it looks like providing a stylesheet from a global-styles.php could be problematic?

@youknowriad
Copy link
Contributor

@nosolosw WordPress already does that though load-styles.php

@oandregal
Copy link
Member Author

Initial docs for this (and related PRs) at #22518

@ellatrix ellatrix mentioned this pull request Jun 16, 2020
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants