Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Transition to global styles roadmap #2403

Closed
Aljullu opened this issue May 5, 2020 · 9 comments
Closed

Transition to global styles roadmap #2403

Aljullu opened this issue May 5, 2020 · 9 comments
Assignees
Labels
type: enhancement The issue is a request for an enhancement.

Comments

@Aljullu
Copy link
Contributor

Aljullu commented May 5, 2020

Gutenberg is working on a new styling system, the Global Style System, and we want to embrace it in WooCommerce Blocks. I tried to draft a plan and wrote down some ideas about how I think we could start supporting it without breaking current themes.

Global Style System summary

This Gutenberg issue has plenty of details, explanations, demos and videos to better understand how the new styling system will work but, how will it affect WooCommerce Blocks? I think it can be summarized as follows:

  • We will get some CSS custom properties (aka variables) that we can (and should) use in our blocks: --wp-gs-colors-text, --wp-gs-colors-background, --wp-gs-colors-primary, etc. Those styles will come from WP, the theme or will be customized by the user. How they are generated shouldn't affect us (it's explained in the GB issue, if you are curious). We should just be aware we can use them, providing good fallbacks.
  • We will be able to register some CSS custom properties so themes and users can style them without the need to write custom CSS selectors. I imagine something like --wp-gs-wc-blocks-cart-card--background--color, so themes could easily change the Cart block card background without the need to write custom CSS selectors.

Limitations

Some limitations we'll face while migrating to the new style system are:

  • We need to support several versions of WordPress. So we can't immediately switch from the 'old-school' styling system to the new one. CSS custom properties might be defined or not depending on the environment (version of WP and Gutenberg).
  • Even when we no longer support WordPress versions which don't support the new styling system, users might still use themes that don't support it. Gutenberg is planning to solve this by prefixing all Global Style System selectors with the .wp-gs class name.
  • IE11 doesn't support CSS custom properties. I think we can ignore this for now, since that's something affecting Gutenberg as well. But listing it here so we are aware.

This is to say that we will need to support the 'old-school' styling system for several months and probably years. So all steps we take towards supporting global styles should be made keeping in mind we can't break previous themes.

Note: I use 'old-school' styling system in order to describe the styling system that currently exists in WordPress: WP/Gutenberg loads some CSS styles, themes load some more and WooCommerce Blocks add some more. All of them end up in a 'specificity-fight', so the most specific styles end up being the ones applied to our blocks.

Roadmap

I identified four different phases between now and the day we completely support the new Global Style System. In the following sections I list some actions I think should be taken in each one of them:

Phase 1: Preparation

There is some low-hanging fruit issues with our styles that I think might be worth fixing before we start thinking on Global Styles. Even though they aren't blocking, fixing them will ease the transition.

  • Font sizes: migrate all font sizes and line-heights to use the font-size() mixin (Migrate all font-size declarations to use the font-size() mixin #2458).
  • Text color: get rid of all text colors and instead always use the inherited one from the theme. For now, my proposal is to use opacity to get different shades of the same color. In the future, when global styles are in place, we will get several CSS custom properties with font colors, like lighter or darker shades. When that happens, we could write a SCSS mixin that uses the lighter shade provided by global styles but has the default color with a lower opacity as a fallback for environments without global styles (Replace all hardcoded font-color declarations with alternatives in the Cart and Checkout blocks #2459).
  • Non text colors: ideally, all our colors should be based on a SCSS variable that in the future we can migrate to a CSS custom property. In order to accomplish this, we first need to evaluate all colors we use in our blocks (see Settling on the correct source for global styles. #1331).
  • Inherited styles: we should default as much as possible to inherited styles. A good example is this PR from @haszari (remove radius from checkout submit button (use theme button style) #2390). Some day we will have a variable --wp-gs-button-borderRadius that we can use to set buttons' border radius. Until that's available (see phase 2), it's better to hardcode as few styles as possible. Another approach is to use inherit or initial in CSS properties were we want to reset styles (in most cases where we might want to use font-family: var( --wp-gs-base-font-family ), we can already use font-family: inherit).
  • Revisit our CSS selectors naming: we have some components whose CSS selector is .wc-block-components- while some others is .wc-block-. When naming CSS custom properties we might end up using the CSS selector as a reference, so it would be good to have this kind of inconsistencies sorted out (Revisit our CSS selectors naming #2457).
  • Define a set of variables that will be used by our blocks: we need to decide which parts of our styles we want to be customizable via CSS custom properties, avoiding them being too specific and instead getting a set of consistent custom properties that can be shared between components (Decide which CSS custom properties will make sense for the Block Styling System #2460).

Phase 2: Consume styles

In a second phase, we could start consuming some of the CSS custom properties in our blocks. I think we shouldn't start doing that until the feature is merged into WordPress core, meaning it's stable enough to build on top of it.

In addition to that, instead of updating all blocks, I think it might make sense to start with a single block (a new one or an already-existing one). This will allow us to get some early feedback before updating other blocks.

In this phase, our CSS will go from things like:

.wc-block-order-summary-item {
	border-bottom: 1px solid $core-grey-light-600;
}

to:

/* This will target old themes or old versions of WP. */
.wc-block-order-summary-item {
	border-bottom: 1px solid $core-grey-light-600;
}
/* This will target environments where global styles are supported. */
.wp-gs .wc-block-order-summary-item {
	border-bottom: 1px solid var( --wp-gs-color-primary-light30, $core-grey-light-600 );
}

Phase 3: Register styles

According to the roadmap, the ability to register styles from third-party blocks will not be included in the first phases of the Global Style System, so registering WC Blocks styles will come in a third phase in our roadmap.

We will not register custom properties for all style declarations, but only the ones we consider should be customizable by themes and users. Registering styles will probably be done via a JSON file: block.json (thanks @nosolosw for pointing me in the right direction with this 🙂 ) .

For example, if we wanted to allow changing the border color of the Order summary items, we would define a --wp-gs-wc-block-order-summary-item--border--color variable:

{
	"wc-block-order-summary-item.borderColor": "#e7eaee",
}

and we would write our CSS as follows:

.wc-block-order-summary-item {
	border-bottom: 1px solid $core-grey-light-600;
}
.wp-gs .wc-block-order-summary-item {
	border-bottom: 1px solid var( --wp-gs-wc-block-order-summary-item--border--color );
}

Like with Phase 2, I think it will be a good idea to start small, with one single block, see how it works, get feedback from the community, and keep updating other blocks after that. This brings us to phase 4...

Phase 4: update all blocks

Once we have proved the actions taken in phase 2 and 3 work and are reliable, we will need to update all old blocks to support the CSS custom properties from the new Global Style System.

Remember in phase 1 we migrated all our font-size and line-height declarations to use the mixin? That will make migrating to CSS custom properties easier. Remember we replaced all our hard-coded colors with SCSS variables? That should make it easier to translate each SCSS variable to a CSS custom property.

Next steps

I would love to hear feedback from @woocommerce/merch-squad. Specially @senadir who did some research on this as well and @haszari who is the Storefront lead.

Also cc'ing @ItsJonQ and @nosolosw who worked a lot on this new style system in Gutenberg, in case you see something out of place in phases 2 and 3 or you find something I might have missed.

Once we iterate with the feedback and we agree on a plan, I think it would be nice to write a P2 about this, so it's not lost once we close this issue, but I wanted to get the discussion happen in GitHub first.

Related P2: pb0Spc-BF-p2.

@Aljullu Aljullu added type: enhancement The issue is a request for an enhancement. action: needs feedback labels May 5, 2020
@Aljullu Aljullu self-assigned this May 5, 2020
@nerrad nerrad mentioned this issue May 5, 2020
@senadir
Copy link
Member

senadir commented May 5, 2020

Thank you @Aljullu for this write-up, I do have some comments:

We need to support several versions of WordPress. So we can't immediately switch from the 'old-school' styling system to the new one. CSS custom properties might be defined or not depending on the environment (version of WP and Gutenberg).

We shouldn't aim to support all of our blocks or WP versions from the get-go, this could be progressive support that users can opt in to, alternative includes styling using CSS.

IE11 doesn't support CSS custom properties. I think we can ignore this for now, since that's something affecting Gutenberg as well. But listing it here so we are aware.

With proper fallbacks, we can generate a hardcoded value above the variable value, it should present the users with a default view of the website, missing the customization.

Text color: get rid of all text colors and instead always use the inherited one from the theme.

This still needs some work before we can start working on it, migrating some of our text to a dedicated class ensure it won't leak opacity to non-text values.

Another approach is to use inherit or initial in CSS properties were we want to reset styles

initial is not supported in IE11. and inherit will hit the nearest parent, our best option is here to omit that value completely and hope the theme value cascade all the way down.

border-bottom: 1px solid var( --wp-gs-color-primary-light30, $core-grey-light-600 );

This will create an extra specificity issue, we can still get around with this, postcss-loaders does it automatically

.wc-block-order-summary-item {
	border-bottom: 1px solid $core-grey-light-600;
	border-bottom: 1px solid var( --wp-gs-color-primary-light30, $core-grey-light-600 );
}

According to the roadmap, the ability to register styles from third-party blocks will not be included in the first phases of the Global Style System, so registering WC Blocks styles will come in a third phase in our roadmap.

My main issue is with this point, the closest we can start actually supporting those systems is around 2021, in our initial discussions, our main issues we old themes and IE11, I think we can skip the waiting period and actually start implementing this system somehow, without fully waiting for it to get a Core version we support it, I understand that we want to leverage an existing system without building something, but I think we're in a unique situation here, the current implementation will still be inadequate and won't be customizable.

@Aljullu
Copy link
Contributor Author

Aljullu commented May 5, 2020

Thanks for the comments @senadir!

We shouldn't aim to support all of our blocks or WP versions from the get-go, this could be progressive support that users can opt in to, alternative includes styling using CSS.

Yes, whether global styles are used will depend on the WP version and whether the theme supports it or not. AFAIK that's how the user "opts in".

With proper fallbacks, we can generate a hardcoded value above the variable value, it should present the users with a default view of the website, missing the customization.

Right, if I'm not wrong that's what Gutenberg is leaning towards right now. But we should keep an eye to see if there are any changes upstream regarding it so we align with Gutenberg.

This still needs some work before we can start working on it, migrating some of our text to a dedicated class ensure it won't leak opacity to non-text values.

I didn't take a deep look at this, there will be some simple and some more complex cases, but I guess wrapping the text with a <span> or a new component would be enough in the complex ones. It's not a small task because we need to review each single string, but the changes required are quite small, so I don't think we will encounter any dead-ends.

initial is not supported in IE11. and inherit will hit the nearest parent, our best option is here to omit that value completely and hope the theme value cascade all the way down.

Ah, good catch with initial, I missed that. I still think using inherit in many cases might help. If we know many themes style heading and buttons but we want to display them as normal text, using font-family: inherit can be handy.

This will create an extra specificity issue, we can still get around with this, postcss-loaders does it automatically

Yes, that's intentional. See the discussion here: WordPress/gutenberg#19883 (comment).

My main issue is with this point, the closest we can start actually supporting those systems is around 2021, in our initial discussions, our main issues we old themes and IE11, I think we can skip the waiting period and actually start implementing this system somehow, without fully waiting for it to get a Core version we support it, I understand that we want to leverage an existing system without building something, but I think we're in a unique situation here, the current implementation will still be inadequate and won't be customizable.

I don't think we want to implement this system in parallel or independently of Gutenberg. To me that sounds like duplicating efforts.

I know we are facing many issues that will be solved with the new Global Style System, but creating a new styling system is a big task if we want to do it right, there are many use-cases to account for and IMO the best thing we can do is to contribute as much as possible to Gutenberg's implementation.

@Aljullu
Copy link
Contributor Author

Aljullu commented May 5, 2020

Expanding on the font-size() mixin, this is how I think it could work:

Phase 2

We update our mixin so it writes styles for environments supporting global styles:

/* _mixins.scss */

@mixin font-size($sizeValue: 16) {
	$relativeSize: $sizeValue / 16;
	font-size: $relativeSize + rem;

	.wp-gs & {
		font-size: calc( var( --wp-gs-fontSizes-base, 1rem ) * #{$relativeSize} );
	}
}

Given this SCSS file (notice we don't need to make any changes in our styles if they are already using the font-size mixin 🎉):

/* blocks/cart/style.scss */

.wc-block-cart {
	@include font-size(16);
}

.wc-block-cart-product-metadata {
	@include font-size(12);
}

This will be the end result:

/* build/style.css */

/* Graceful degradation for environments without global styles. */
.wc-block-cart {
	font-size: 1rem;
}

.wc-block-cart-product-metadata {
	font-size: 0.75rem;
}

/* If the WP version, the theme and the browser support global styles, we honor them. */
.wp-gs .wc-block-cart {
	font-size: calc( var( --wp-gs-fontSizes-base, 1rem ) * 1);
}

.wp-gs .wc-block-cart-product-metadata {
	font-size: calc( var( --wp-gs-fontSizes-base, 1rem ) * 0.75);
}

This way, if the theme or the user modified the --wp-gs-fontSizes-base custom property, that will be honored in our blocks, without breaking compatibility with old environments.

Phase 3

We can go a step further and add our own custom properties, like --wp-gs-wc-block-cart--font--size:

/* blocks/cart/style.scss */

.wc-block-cart {
	--wp-gs-fontSizes-base: var( --wp-gs-wc-block-cart--font--size, --wp-gs-fontSizes-base, 1rem);
	@include font-size(16);
}

.wc-block-cart-product-metadata {
	@include font-size(12);
}

Now, let's imagine a theme wants to make the font a bit smaller for the Cart block, so it could write something like this:

:root {
	--wp-gs-wc-block-cart--font--size: 0.9rem;
}

The generated CSS will be:

/* build/style.css */

.wc-block-cart {
	font-size: 1rem; // 16px
}

.wc-block-cart-product-metadata {
	font-size: 0.75rem; // 12px
}

.wp-gs .wc-block-cart {
	font-size: calc( var( --wp-gs-fontSizes-base /* =0.9rem */, 1rem ) * 1); // =14.4px
}

.wp-gs .wc-block-cart-product-metadata {
	font-size: calc( var( --wp-gs-fontSizes-base /* =0.9rem */, 1rem ) * 0.75); // =10.8px
}

@senadir
Copy link
Member

senadir commented May 5, 2020

I know we are facing many issues that will be solved with the new Global Style System, but creating a new styling system is a big task if we want to do it right, there are many use-cases to account for and IMO the best thing we can do is to contribute as much as possible to Gutenberg's implementation.

I understand that creating a system is a big task, my point was to evaluate if we can use the same existing code from a @wordpress/* package directly in our code, thereby shipping it early for our blocks, and disabling it if we detect support for global styles, granted, this is still an effort, and should be evaluated before committing to it

@haszari
Copy link
Member

haszari commented May 5, 2020

This plan is looking great to me @Aljullu - nice work 🙌 👏. I'm looking forward to getting stuck in! I really like the "principles" that you've outlined in each phase :)

Regarding Storefront, I don't have enough experience with Storefront's css approach (though I can confirm it is in the old-school category) to know if there are any blockers/issues there. However, I think whatever we do we're likely to need follow up in Storefront to support it. The gradual/phased pace of your roadmap should work well here.

For example, when we've implemented Phase 1 in blocks, that gives us a set of expectations that we can test in Storefront (and other popular Woo themes), and we can fix any issues that come up. Probably a good idea for us to do that work in parallel - e.g. test Storefront (etc) as we iterate on Phase 1. If there are problems then we can come up with good fix patterns and apply to themes, or worst case, tweak the plan as needed.

@nerrad
Copy link
Contributor

nerrad commented May 7, 2020

@Aljullu really great job on writing this up and identifying some clear phases to the process. It makes it easier to follow along with the actionable steps and pre-requisites for rolling things out. The plan sounds good and I think it's really close to the direction we should take. I just have a few points to raise:

  • With css variable naming, I think we should try to avoid being too specific with variables (eg --wp-gs-wc-block-order-summary-item--border--color). To bring consistency we should identify common shared elements across all the ui/ux and name variables according to those elements, so for example the above example might become something like --wp-gs-wc-block-panel--border--color. The more specific we get in variable names, the harder it is to maintain consistency across the design of the blocks. This is where you can likely align with some of the work being done this sprint in finding those inconsistencies and fixing them.
  • I think there'd be good value in tracking what you implement as you go in a markdown doc or something that serves as a record of the design system being implemented so that when it's all done it's much easier to document (and could potentially help reviewers spot inconsistencies that are introduced in a pull).

@haszari
Copy link
Member

haszari commented May 7, 2020

identify common shared elements across all the ui/ux and name variables according to those elements
markdown doc or something that serves as a record of the design system being implemented

Great points @nerrad - thanks for picking up on this. I agree - we should strive to name our colours/variables with high-level semantic names as much as possible.

As you've noted - this is the crux of building a design system, so we should definitely document this as we go and work closely with our designer friends (and customer feedback/real stores if possible) to get those high-level concepts right 🎨

@Aljullu
Copy link
Contributor Author

Aljullu commented May 8, 2020

  • With css variable naming, I think we should try to avoid being too specific with variables (eg --wp-gs-wc-block-order-summary-item--border--color). To bring consistency we should identify common shared elements across all the ui/ux and name variables according to those elements, so for example the above example might become something like --wp-gs-wc-block-panel--border--color. The more specific we get in variable names, the harder it is to maintain consistency across the design of the blocks. This is where you can likely align with some of the work being done this sprint in finding those inconsistencies and fixing them.
    I agree - we should strive to name our colours/variables with high-level semantic names as much as possible.

💯 on this. In addition, I think we should discuss with designers which variables make more sense to them. I will add a task to plan the variables in the preparation phase bullet list.

I think there'd be good value in tracking what you implement as you go in a markdown doc or something that serves as a record of the design system being implemented so that when it's all done it's much easier to document (and could potentially help reviewers spot inconsistencies that are introduced in a pull).

Sounds like a good idea. Could we use the repo wiki for that? I see we are not making use of it, but that sounds like a good opportunity.


Thanks @senadir @haszari @nerrad for the feedback. I will prepare a P2 for next week with the roadmap with the feedback applied.

@Aljullu
Copy link
Contributor Author

Aljullu commented May 15, 2020

I will proceed closing this issue for now, the roadmap received good feedback and it was posted in a P2 as well: pb0Spc-BF-p2. Issues for the Preparation tasks were created and I added the links in the issue intro.

Once we start implementing it, we can start a docs page in the repo or the wiki along with other documentation for styling.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: enhancement The issue is a request for an enhancement.
Projects
None yet
Development

No branches or pull requests

4 participants