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(elevation): move elevation rules into theme stylesheets #11344

Merged
merged 1 commit into from Sep 18, 2018

Conversation

benelliott
Copy link
Contributor

Move all usages of elevation mixins out of component stylesheets and into their respective themes.
This allows the elevation color to be changed based on the theme. Add new mat-theme-elevation
and mat-theme-overridable-elevation shorthand mixins to apply the current theme's elevation
color. Replace all usages of mat-elevation mixins with themed equivalents. Add elevation
property to the default foreground theme palettes.

Closes #11343

BREAKING CHANGE:

Because mat-elevation usages have been moved out of component stylesheets, users who have
not invoked a theme mixin will not see any elevation shadows on Material components.
However, users that have created a custom theme which lacks the elevation property will
still see the default black shadows.

Additionally, users who want to use themed elevations in their custom components can create
their own shorthand mixin:

@import '~angular/material/theming';

$myTheme: ...

@mixin my-elevation($zValue) {
  @include mat-theme-elevation($zValue, $myTheme);
}

and then invoke angular-material-theme with the $myTheme variable.

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label May 15, 2018
@benelliott
Copy link
Contributor Author

Example of using this feature in a custom theme - setting elevation to violet:

violet-elevation

@jelbourn
Copy link
Member

@benelliott are you saying this is only breaking when a theme is missing? If that's the case, it wouldn't be considered breaking because a theme has always been required.

@benelliott
Copy link
Contributor Author

@jelbourn The situations I can think of are:

  1. The user uses a built-in theme - these themes have the foreground.elevation property set to black so this is the same as before
  2. The user uses a custom theme - the mat-theme-elevation mixin defaults the color to black if the theme map returns null so this is the same as before
  3. The user uses no theme - in this case, there will be no shadow

So yes I think so, unless there is a situation I'm not thinking of!

@@ -151,6 +151,14 @@ $_mat-elevation-prefix: 'mat-elevation-z';
#{map-get(_get-ambient-map($color, $opacity), $zValue)};
}

@mixin mat-theme-elevation($zValue, $theme, $opacity: $mat-elevation-opacity) {
Copy link
Member

Choose a reason for hiding this comment

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

The new mixins need descriptions similar to the existing ones

@@ -151,6 +151,14 @@ $_mat-elevation-prefix: 'mat-elevation-z';
#{map-get(_get-ambient-map($color, $opacity), $zValue)};
}

@mixin mat-theme-elevation($zValue, $theme, $opacity: $mat-elevation-opacity) {
$foreground: map-get($theme, foreground);
$elevation-color: map-get($foreground, elevation);
Copy link
Member

Choose a reason for hiding this comment

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

Typically the background and foreground palettes are fixed regardless of theme; how would you go about changing the color of the shadow?

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 took the position that wanting to change the elevation color was a fairly advanced use case, so it would be admissible for it to be changed by providing angular-material-theme with a fully custom theme map (as opposed to using the mat-light-theme and mat-dark-theme functions). This is what I do in a project where I want full control over the colors used in the app, however it has just occurred to me that it may not be part of the public API(?).

An alternative solution could be to provide it as an optional fourth argument to the mat-light-theme and mat-dark-theme functions (with default value black), and then to convert the $mat-light-theme-foreground and $mat-dark-theme-foreground variables into functions that take the elevation color as their only argument.

Copy link
Member

Choose a reason for hiding this comment

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

@josephperrott and I took a closer look at this, and found that we're going to have some cases in Google where it will be more common to want to customize the shadow color based on the theme colors, so we probably want to make it more ergonomic to customize the shadow based on that.

We'd also want to avoid adding a lot of excess css to the theme so most people wouldn't end up using. I'm still thinking about a good way to approach it.

Copy link
Contributor Author

@benelliott benelliott May 16, 2018

Choose a reason for hiding this comment

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

@jelbourn Perhaps the additional parameter to the theme functions could be used instead?

An alternative way to avoid adding CSS to the themes could be to remove all internal usages of the mixins, and only to rely on the .mat-elevation-z? classes for applying elevation to Material components. This approach would actually reduce the amount of CSS overall, as only the output of

 @for $zValue from 0 through 24 {
    .#{$_mat-elevation-prefix}#{$zValue} {
      @include mat-theme-elevation($zValue, $theme);
    }
  }

would be rendered (component stylesheets would be smaller as they no longer include the box shadow rules).

Perhaps overridable elevation could then be implemented like this:

$_mat-overridable-elevation-prefix: 'mat-overridable-elevation-z';

 @for $zValue from 0 through 24 {
    .#{$_mat-overridable-elevation-prefix}#{$zValue}:not([class*='#{$_mat-elevation-prefix}']) {
      @include mat-theme-elevation($zValue, $theme);
    }
  }

and the old mat-overridable-elevation mixin would be deleted.

Copy link
Member

Choose a reason for hiding this comment

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

I like the idea of using the common set of css classes for everything. We would have to make sure they're still easily overridable, though.

I guess what this PR is really about is being able to customize the base shadow color, which makes sense to be in the foreground palette. If we want to set a shadow based on another palette, I don't see a way around explicitly passing the color in the component's theme 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 think it boils down to two approaches:

1) Extend the current elevation mixins to support themes, and move their usages to the theme stylesheets (as in the current PR).

Advantages:

  • Code changes are minimal
  • CSS size increase is negligible

Disadvantages:

  • Moving elevation rules to the theme stylesheets means that everyone's CSS gets larger, regardless of whether they use those components
  • Size of elevation CSS will increase linearly with the number of components added to the library

2) Incorporate the theme color into the mat-elevation-z* CSS classes and only use these classes to apply elevation to components

Advantages:

  • CSS size will not increase as components are introduced to the library
  • CSS size may actually be reduced, as there is currently duplication from using the mixin in both the mat-elevation-z classes and the internal component stylesheets
  • Since elevation rules can only come from one set of classes, inspecting element elevation becomes simpler

Disadvantages:

  • Components will now have to directly apply their own elevation rules in TypeScript. This is potentially a major refactor - for example, MatButton will have to apply mat-elevation-z8 if it has the mat-raised-button attribute set. This logic in itself may be trivial but it would require a wave of new unit tests
  • Will probably have to remove the $_mat-elevation-prefix variable and just use the static string if elevation is applied statically as classes in component templates (alternately, could mirror this variable in TypeScript and only ever apply these classes in TypeScript within the library)

I'm happy to take a shot at the second option if you think it is more appropriate.

@jelbourn
Copy link
Member

jelbourn commented Jun 6, 2018

@crisbeto do you have any opinions on this? I would lean towards just making the elevation part of the theme solely because it's a simpler change

@crisbeto
Copy link
Member

crisbeto commented Jun 6, 2018

Keeping it in the theme sounds good. My only nit is that, IMO, the new mixins should be made private (prefixed with an underscore) since I don't see them being particularly useful for consumers.

@ngbot
Copy link

ngbot bot commented Jun 7, 2018

Hi @benelliott! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

1 similar comment
@ngbot
Copy link

ngbot bot commented Jun 7, 2018

Hi @benelliott! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

@benelliott
Copy link
Contributor Author

Rebased and added suggestion from @crisbeto.

@benelliott
Copy link
Contributor Author

@crisbeto Is there anything else you would like me to change before this can be merged?

Copy link
Member

@crisbeto crisbeto left a comment

Choose a reason for hiding this comment

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

LGTM. Leaving the final say to @jelbourn.

@jelbourn
Copy link
Member

I'm running a presubmit of this PR against Google apps to make sure it doesn't cause any breakages

@benelliott
Copy link
Contributor Author

Cool, thanks.

@ngbot
Copy link

ngbot bot commented Jul 12, 2018

Hi @benelliott! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

@mmalerba
Copy link
Contributor

@jelbourn what happened with the presubmit on this one, should we mark lgtm, merge-ready?

@jelbourn
Copy link
Member

Presubmit was black across the board, need to update some build files for another pass
(I went through one round of this already but ended u getting merge conflicts and had to restart)

@benelliott
Copy link
Contributor Author

Hi @jelbourn, I've just rebased to resolve the conflicts. Is black good or bad for a presubmit?

@mmalerba mmalerba added pr: lgtm action: merge The PR is ready for merge by the caretaker labels Jul 17, 2018
@ngbot
Copy link

ngbot bot commented Jul 17, 2018

I see that you just added the pr: merge ready label, but the following checks are still failing:
    failure missing required label: "target: *"
    failure status "continuous-integration/travis-ci/pr" is failing

If you want your PR to be merged, it has to pass all the CI checks.

If you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help.

@benelliott benelliott force-pushed the elevation-theme branch 2 times, most recently from 357e85b to a05cf07 Compare September 11, 2018 16:31
@benelliott
Copy link
Contributor Author

@mmalerba Nice - rebased. Not sure why ngbot didn't ping me about the conflicts this time round.

@mmalerba mmalerba added the P2 The issue is important to a large percentage of users, with a workaround label Sep 11, 2018
@ngbot
Copy link

ngbot bot commented Sep 11, 2018

Hi @benelliott! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

@mmalerba mmalerba force-pushed the elevation-theme branch 2 times, most recently from a42b68a to 6d1818d Compare September 12, 2018 15:49
&:not([disabled]):active {
@include mat-overridable-elevation(8);
}

&[disabled] {
box-shadow: none;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this needs to move to the theme too, I'm seeing screenshots with disabled buttons that have shadows (this is basically the equivalent of mat-elevation(0))

Copy link
Contributor

Choose a reason for hiding this comment

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

card has a similar one that should go into the theme file:

&.mat-card-flat {
  box-shadow: none;
}

Move all usages of elevation mixins out of component stylesheets and into their respective themes.
This allows the elevation color to be changed based on the theme. Add new `mat-theme-elevation`
and `mat-theme-overridable-elevation` shorthand mixins to apply the current theme's elevation
color. Replace all usages of `mat-elevation` mixins with themed equivalents. Add `elevation`
property to the default `foreground` theme palettes.

Closes angular#11343

BREAKING CHANGE:

Because `mat-elevation` usages have been moved out of component stylesheets, users who have
not invoked a theme mixin will not see any elevation shadows on Material components.
However, users that have created a custom theme which lacks the `elevation` property will
still see the default black shadows.

Additionally, users who want to use themed elevations in their custom components can create
their own shorthand mixin:

```
@import '~angular/material/theming';

$myTheme: ...

@mixin my-elevation($zValue) {
  @include mat-theme-elevation($zValue, $myTheme);
}

```

and then invoke `angular-material-theme` with the `$myTheme` variable.
@benelliott
Copy link
Contributor Author

Hi @mmalerba, I've addressed your comments + rebased + given the flat card and disabled buttons a quick once-over on the demo app.

I decided to use elevation 0 instead of box-shadow: none to preserve the level of abstraction. Let me know if you want me to change that.

@mmalerba mmalerba merged commit 9c075f5 into angular:master Sep 18, 2018
@benelliott
Copy link
Contributor Author

🎉🎉🎉

devversion added a commit to devversion/material2 that referenced this pull request Sep 23, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: angular#11344 has been merged)
devversion added a commit to devversion/material2 that referenced this pull request Sep 23, 2018
* Fixes a remaining elevation style which is not created inside of the theme. (related to: angular#11344)
devversion added a commit to devversion/material2 that referenced this pull request Sep 24, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: angular#11344 has been merged)
@jelbourn jelbourn added target: major This PR is targeted for the next major release and removed target: patch This PR is targeted for the next patch release labels Sep 24, 2018
jelbourn pushed a commit that referenced this pull request Sep 25, 2018
Fixes a remaining elevation style which is not created inside of the theme. (related to: #11344)
roboshoes pushed a commit to roboshoes/material2 that referenced this pull request Oct 23, 2018
Fixes a remaining elevation style which is not created inside of the theme. (related to: angular#11344)
vivian-hu-zz pushed a commit that referenced this pull request Nov 6, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: #11344 has been merged)
devversion added a commit to devversion/material2 that referenced this pull request Nov 8, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: angular#11344 has been merged)
devversion added a commit to devversion/material2 that referenced this pull request Nov 10, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: angular#11344 has been merged)
andrewseguin pushed a commit that referenced this pull request Nov 14, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: #11344 has been merged)
IlCallo pushed a commit to IlCallo/material2 that referenced this pull request Nov 15, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: angular#11344 has been merged)
josephperrott pushed a commit that referenced this pull request Nov 19, 2018
* Currently if chips are disabled with the spec 2018 alignment, it's not clear whether a chip is disabled or not. The chip still has a focus effect, hover effect and pointer cursor for the `mat-chip-remove`.
* Also moves the `@include mat-elevation` to the theme (probably introduced before: #11344 has been merged)
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement P2 The issue is important to a large percentage of users, with a workaround target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(elevation): Add ability to change the color of Material component shadows within a theme
5 participants