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

feat(theme): Add support for CSS vars with fallback #4470

Merged
merged 15 commits into from
Mar 14, 2019

Conversation

patrickrodee
Copy link
Contributor

@patrickrodee patrickrodee commented Mar 1, 2019

What this does
Add the ability to specify a CSS custom property name and fallback for color mixins. Allows clients that can support CSS custom property theming to use that when desired without breaking browsers that do not support CSS custom properties.

What this does not do
This does not establish naming conventions for CSS custom properties. Those names are entirely up to the developers who use this feature.

Usage

.my-custom-button {
  @include mdc-button-fill((
    varname: --my-custom-button-fill,
    fallback: purple,
  ));
}

The generated CSS is as follows:

.my-custom-button {
  background-color: purple;
  background-color: var(--my-custom-button-fill, purple);
}

This CSS allows for browsers that do not support CSS custom properties to default to the fallback (purple) while still supporting an overridable CSS custom property --my-custom-button-fill.

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit 5d49c5a vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit 7d985e2 vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit fd51863 vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit 195bcba vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit a43e2ff vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit bdebc93 vs. master! 💯🎉

@abhiomkar
Copy link
Contributor

I think this is a great addition to add support for CSS custom property in overriding component styles! 👍

I've a suggestion in the way we use the mixin, instead of changing the style argument structure I added a way to auto detect the presence of CSS custom property and extract the fallback color automatically.

// theme/_mixins.scss

@mixin mdc-theme-css-var($property, $var, $important: false, $edgeOptOut: false) {
  @if is-css-var($var) {
    $fallback-style: get-fallback-style($var); // Extracts fallback color from css custom property.
    @include mdc-theme-prop($property, $fallback-style, $important: $important, $edgeOptOut: $edgeOptOut);
    @include mdc-theme-prop($property, $var, $important: $important, $edgeOptOut: $edgeOptOut);
  } @else {
    @include mdc-theme-prop($property, $var, $important: $important, $edgeOptOut: $edgeOptOut)
  }
}

// button/_mixins.scss

@mixin mdc-button-container-fill-color($color) {
  &:not(:disabled) {
    @include mdc-theme-css-var(background-color, $color, $edgeOptOut: true);
  }
}

// override.scss

.my-custom-button {
  @include mdc-button-container-fill-color(var(--my-custom-button-color, purple));
}

WDYT?

@patrickrodee
Copy link
Contributor Author

@abhiomkar I originally thought about that but felt the results were a little too "magic." My intention was to make it very clear that a fallback value had to be specified and what role it served. The suggested change also has side-effects for anyone already passing var(--custom-prop, purple) to a mixin. I was hoping to avoid any side-effects with this change and make it purely opt-in.

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit f5dfc59 vs. master! 💯🎉

Copy link
Contributor

@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.

Thanks for the clarification!

Aren't we already including fallback CSS with theme literals (primary, secondary etc)? Do you think adding an additional flag to mdc-theme-prop mixin (for example, fallback: false) would resolve opt-in issue?

packages/mdc-theme/_functions.scss Outdated Show resolved Hide resolved
packages/mdc-theme/_mixins.scss Show resolved Hide resolved
@@ -129,6 +129,10 @@ $mdc-theme-property-values: (
//
// NOTE: This function must be defined in _variables.scss instead of _functions.scss to avoid circular imports.
@function mdc-theme-prop-value($style) {
@if mdc-theme-is-var-with-fallback_($style) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Returning the new style type as is causes an issue to other mixins that uses mdc-theme-prop-value() function. For example, mdc-card-outline uses this function to set border-color. mdc-card/_mixins.scss:L303

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can we update that line to be as follows?

@include mdc-theme-prop(border-color, $color);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

List divider uses the approach described above. I'll include that update in this PR.

@include mdc-theme-prop(border-bottom-color, $color);

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused though, what issue was this causing? Do we need to be concerned for existing valid cases of mdc-theme-prop-value being used?

Copy link
Contributor

Choose a reason for hiding this comment

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

It is still an issue if component needs to mix colors or apply opacity using rgba() sass function.

For example, dialog uses rgba() to apply opacity to color.

dialog/_mixins.scss:

background-color: rgba(mdc-theme-prop-value($color), $opacity);

Where, mdc-theme-prop-value returns new color format which rgba function doesn't support.

This is another advanced use case where text field uses mix() function two mix two colors:

textfield/_variables.scss:

$mdc-text-field-background:
    mix(mdc-theme-prop-value(on-surface), mdc-theme-prop-value(surface), 4%);

Copy link
Contributor

@abhiomkar abhiomkar Mar 13, 2019

Choose a reason for hiding this comment

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

@kfranqueiro It shouldn't break existing valid usage. This is an issue only for users who send new color format to component's mixins.

mdc-dialog-title-ink-color('purple'); // works
mdc-dialog-title-ink-color({
  varname: '--custom-css-var-ink-color',
  fallback: purple
}); // breaks since this applies opacity on given color using rgba

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mdc-theme-prop-value has been updated to always return the fallback value.

@function mdc-theme-prop-value($style) {
@if mdc-theme-is-var-with-fallback_($style) {
@return mdc-theme-get-var-fallback_($style);
}
@if mdc-theme-is-valid-theme-prop-value_($style) {
@return $style;
}

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit ef5d84f vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit a0293a0 vs. master! 💯🎉

@patrickrodee
Copy link
Contributor Author

@abhiomkar I think that would only work for the existing CSS custom properties (primary, secondary). I'm intending to support arbitrary CSS custom properties.

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit 65a61b0 vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit e58979e vs. master! 💯🎉

Copy link
Contributor

@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.

@patrickrodee That should work for arbitrary CSS custom properties too if mdc-theme-prop can detect the presence of CSS customer property and apply fallback CSS value with opt-in flag.

@include mdc-theme-prop(color, var(--my-custom-color, purple), fallback: true);

generates:

color: purple;
color: var(--my-custom-color, purple);

packages/mdc-card/_mixins.scss Outdated Show resolved Hide resolved
@@ -110,6 +110,38 @@ Property Name | Description
`on-secondary` | A text/iconography color that is usable on top of secondary color
`on-surface` | A text/iconography color that is usable on top of surface color

#### `mdc-theme-prop` with CSS Custom Properties

> **Note** The Sass map `$style` argument is intended *only* for use with color mixins.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see why we can't use it for other CSS properties. We aren't doing anything specific with color in our implementation?

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 haven't tested it for other CSS custom properties. I'd rather scope this to what it was intended for. We can always remove this line from the docs at a later date.

packages/mdc-theme/README.md Outdated Show resolved Hide resolved
packages/mdc-theme/README.md Outdated Show resolved Hide resolved

```
.foo {
@include mdc-theme-prop(color, (
Copy link
Contributor

Choose a reason for hiding this comment

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

If I understand this correctly, this is equivalent to applying same mixin with CSS custom property and regular CSS value?

mdc-button-fill-color(purple);
mdc-button-fill-color(var(--my-custom-button, purple));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The output CSS is pretty different. Calling both mixins includes the full selector twice. Below is an approximation of the output CSS:

.mdc-button {
  background-color: purple;
}
.mdc-button {
  background-color: var(--my-custom-button, purple);
}

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit 5643f95 vs. master! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 627 screenshot tests passed for commit b92a208 vs. master! 💯🎉

Copy link
Contributor

@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.

LGTM.

@patrickrodee patrickrodee merged commit 0bfb393 into master Mar 14, 2019
@patrickrodee patrickrodee deleted the feat/theme/vars-with-fallback branch March 14, 2019 21:47
adrianschmidt pushed a commit to Lundalogik/material-components-web that referenced this pull request Mar 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants