Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

feat: Add feature targeting support and apply to mdc-button #4228

Merged
merged 23 commits into from
Jan 18, 2019

Conversation

kfranqueiro
Copy link
Contributor

This adds a mdc-feature-targeting package to support the effort summarized in #4227, and converts the mdc-button package (making necessary adjustments to mdc-ripple to allow it).

Many thanks to @mmalerba for spearheading the initial design and implementation.

The most important thing to note about the feature-targeting infrastructure is that it should be used as little as necessary to provide the granularity outlined in #4227 - i.e., $query is only passed down as far as it needs to be passed to ensure this granularity. It is not passed to every single mixin.

This PR also adds a new test script to verify that nothing is missed when feature-targeting. All this requires to work is that as we restructure each package's SCSS, we add an import for it in test/scss/feature-targeting.scss.

@codecov-io
Copy link

codecov-io commented Jan 4, 2019

Codecov Report

Merging #4228 into master will decrease coverage by 0.29%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##           master    #4228     +/-   ##
=========================================
- Coverage   98.87%   98.58%   -0.3%     
=========================================
  Files         127      127             
  Lines        5705     5705             
  Branches      762      762             
=========================================
- Hits         5641     5624     -17     
- Misses         64       81     +17
Impacted Files Coverage Δ
packages/mdc-radio/index.js 84.61% <0%> (-10.26%) ⬇️
packages/mdc-switch/index.js 91.83% <0%> (-6.13%) ⬇️
packages/mdc-tabs/tab/index.js 90.9% <0%> (-6.07%) ⬇️
packages/mdc-base/component.js 95.83% <0%> (-4.17%) ⬇️
packages/mdc-tab/index.js 92.98% <0%> (-3.51%) ⬇️
packages/mdc-ripple/util.js 96.49% <0%> (-3.51%) ⬇️
packages/mdc-auto-init/index.js 97.22% <0%> (-2.78%) ⬇️
packages/mdc-ripple/index.js 97.91% <0%> (-2.09%) ⬇️
packages/mdc-checkbox/index.js 98.79% <0%> (-1.21%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 017ecb6...9677b66. Read the comment docs.

Copy link
Contributor

@moog16 moog16 left a comment

Choose a reason for hiding this comment

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

First pass...I think I have a pretty good understanding, but it took me a bit to understand the new feature-targeting package. The cyclomatic-complexity is quite high, which takes some time to trace. Its a cool system with a lot of bells and whistles (so I see why we went this route).

packages/mdc-feature-targeting/_mixins.scss Outdated Show resolved Hide resolved
packages/mdc-button/_mixins.scss Outdated Show resolved Hide resolved
packages/mdc-button/_mixins.scss Outdated Show resolved Hide resolved
packages/mdc-button/_mixins.scss Outdated Show resolved Hide resolved
packages/mdc-ripple/_mixins.scss Show resolved Hide resolved
packages/mdc-ripple/_mixins.scss Show resolved Hide resolved
packages/mdc-ripple/_mixins.scss Show resolved Hide resolved
packages/mdc-ripple/common.scss Outdated Show resolved Hide resolved
Copy link
Collaborator

@abhiomkar abhiomkar left a comment

Choose a reason for hiding this comment

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

It took me a while to completely understand what's happening just by looking at the code.

I like the idea of allowing fine grained control of emitting CSS based on target features. This also brings lot of complexity into the system. I echo Matt's point here.

I've only looked at the mdc-button/ and mdc-feature-targeting/ packages & I've few questions / suggestions.

Can we group the features into a separate mixins and use each feature as al-carte?

For example,

.mdc-button {
  @include mdc-button-common;
  @include mdc-button-feature-all;
}

@mixin mdc-button-feature-all {
  // These mixins can be used individually only if needed.
  @include mdc-button-feature-typography;
  @include mdc-button-feature-color;
  @include mdc-button-feature-structure;
}

@mixin mdc-button-common {
  @include mdc-ripple-surface;
  @include mdc-ripple-radius-bounded;
  @include mdc-states(primary);
  ...
}

@mixin mdc-button-feature-typography {
  @include mdc-typography(button);
}

@mixin mdc-button-feature-color {
  @include mdc-button-ink-color(primary);

  .mdc-button--raised,
  .mdc-button--unelevated {
    @include mdc-button-container-fill-color(primary);
    @include mdc-button-ink-color(on-primary);
  }
}

@mixin mdc-button-feature-structure {
  @include mdc-button-shape-radius(small);
  ...
}

I'm sure you might've thought about this, was there any challenges with this approach? :)

Also, It would be great to see how much of CSS (or bytes) we're saving before & after this change.

@kfranqueiro
Copy link
Contributor Author

Regarding CSS file size before/after, the difference should ideally be zero. The reason this is structured the way it is is to be able to easily verify that we're outputting the same styles before and after these changes.

I wonder if your other idea RE organization occurred to @mmalerba (I suspect he was struck with a few ideas as he prototyped this). The main drawback I can think of for the purposes of the conversion itself is that it'd make it harder to glance at the generated CSS before/after to confirm they're the same, because it would likely reorder a bunch of styles (in a way that is harmless, but would require a lot more careful inspection of diffs, especially once we get into e.g. text field). I think @mmalerba purposely aimed for keeping the output CSS identical to before.

I definitely agree that the feature-targeting package can be hard to grok at first - and that makes me realize it doesn't yet have a README here. I'd like to get this in first so that people can start pushing forward with more conversions (the Angular team is interested in helping out), but I'm happy to take on writing the README (perhaps with a review from Miles) separately.

@mmalerba
Copy link
Collaborator

@abhiomkar Yes, I did consider just having separate mixins for each feature, but I felt their were a number of advantages this approach had over it:

  • It doesn't require breaking changes to the current mixin API. If we wanted to use the separate mixin approach we would need to split up the current mixins
  • It can be done in a way that results in zero changes to the output CSS. Refactoring the CSS can be really tricky, as even just reordering lines can change what rules get applied in the end.
  • It allows us to group together all styles that apply to a single class. This might be a personal preference thing, but I think it's nice to be able to see all of the styles that are being applied to .mdc-button in one place, rather than having to go look for the selector in each of the separate feature mixins.
  • It's more powerful than just having separate mixins because it allows combinations of features (e.g. get all styles that apply to either color or typography, get all styles that apply to both color and typography, get all styles that apply to color but not animations, etc)

@mdc-web-bot
Copy link
Collaborator

All 758 screenshot tests passed for commit 22d6e7d vs. master! 💯🎉

packages/mdc-button/_mixins.scss Outdated Show resolved Hide resolved
packages/mdc-button/_mixins.scss Show resolved Hide resolved
packages/mdc-button/_mixins.scss Show resolved Hide resolved
//

// Creates a feature target from the given feature query and targeted feature.
@function mdc-feature-create-target($feature-query, $targeted-feature) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

@kfranqueiro kfranqueiro Jan 18, 2019

Choose a reason for hiding this comment

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

I'm inclined to tackle this along with the README for the feature-targeting package, in a follow-up PR.

(Edit: Logged #4266)

packages/mdc-feature-targeting/_functions.scss Outdated Show resolved Hide resolved
@mdc-web-bot
Copy link
Collaborator

All 758 screenshot tests passed for commit 9d7bf83 vs. master! 💯🎉

packages/mdc-button/_mixins.scss Outdated Show resolved Hide resolved
packages/mdc-button/_mixins.scss Show resolved Hide resolved
packages/mdc-button/_mixins.scss Outdated Show resolved Hide resolved
background-color $mdc-states-wash-duration linear;
}

@include mdc-feature-targets($feat-structure) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it is safe to merge these structure style to above feat-structure block.

Comment applies across this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I gave this a try in a few places, but I'm ultimately deciding against it for 2 reasons:

  1. There are different selectors in the block above vs. here, whereas this block currently incorporates structure and animation styles for the same selector. I'd argue this is easier to read, because it's closer to how you would read raw CSS prior to the feature-targeting split (it's just a set of properties under the same selector).

  2. Moving this to the other selector causes more output CSS due to needing to duplicate selectors. That effect is then multiplied by the number of components that @include ripple mixins.

In contrast, when there are cases of multiple disjointed mdc-feature-targets calls on the same feature under the same exact selector, those are much more likely to make sense to merge together (Miles and I identified a few on his checkbox PR #4258, for example). But this case is more complex.

I did make a couple of tweaks here and in button to attempt to make more selectors easier to spot, by moving selectors outside feature-targets invocations (again taking advantage of Sass being smart enough to prune empty blocks).

packages/mdc-ripple/_mixins.scss Show resolved Hide resolved
Copy link
Contributor

@moog16 moog16 left a comment

Choose a reason for hiding this comment

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

LGTM

@mdc-web-bot
Copy link
Collaborator

All 758 screenshot tests passed for commit 9677b66 vs. master! 💯🎉

@kfranqueiro kfranqueiro merged commit 531dffb into master Jan 18, 2019
@kfranqueiro kfranqueiro deleted the experimental/feature-targeting branch January 18, 2019 23:41
@jamesmfriedman jamesmfriedman mentioned this pull request Feb 5, 2019
24 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants