angular / material

Material design for AngularJS
https://material.angularjs.org/
MIT License
16.55k stars 3.39k forks source link

Differntiate inside single theme. #537

Closed SanderElias closed 9 years ago

SanderElias commented 9 years ago

I need to build an app that needs to be in one color-scheme. What I mean by this, I can only set the theme once, on the highest level. Inside my app, I need a way to differentiate my elements.

I looked for some styles like this: md-warn md-danger md-primary md-secondary md-error md-success

But I could not find those! Found quite some nice things while reading trough the material css and scss files, but somehow I seemed to have missed out on these!

Als0 it would be nice to have access to the color palette as defined in the design spec. It would be really handy to have things like this:

md-color-50, md-color-100 etc, where both the color and the background color, would be set as in the color palette.

WillsB3 commented 9 years ago

If you use the new theming system in the latest release you can use the SASSs map-get function to retrieve a colour variant for your current colour scheme. There are more details here

SanderElias commented 9 years ago

@WillsB3, I know. But that would require me to recompile the sass. I don't mind doing that, but it is something that needs to be available to every MD-user. (as far as I know, the SASS map-get is not available in the browser!)

ajoslin commented 9 years ago

Feel free to use different themes on different elements. For example, use md-theme="amber" and set 'md-primary' if you want an amber button.

SanderElias commented 9 years ago

That's not what I meant. A theme is meant to style an application. Not to convey meaning. You need to differentiate within a single color theme. If your app is running for different customers, those customers all want their own color-theme. But within such an app, you sometimes need convey meaning to the end-user (where the end-user is a customer of the customer!). That means that on a given point, you don't know what the theme is that's chosen, so selecting a different theme on a element might render a butt-ugly result.

plato-cambrian commented 9 years ago

+1 for attributes or classes for setting shade, perhaps .md-primary-shade-50 or md-primary-shade="50".

I've always just set my own classes for highlight colors, but I could see the utility with md-warn md-danger md-error md-success defaults, even if they just copy bootstrap's.

See also https://github.com/angular/material/issues/521


edit: as you say

That means that on a given point, you don't know what the theme is that's chosen, so selecting a different theme on a element might render a butt-ugly result.

which is an argument against default highlight colors

SanderElias commented 9 years ago

Ok, I'm working toward an (partial) solution on this. If anybody want to pick this up, drop me a note, so we can work together on this. It's a bit more involved then it looks at the first eye. But I'm well on my way.

WillsB3 commented 9 years ago

@SanderElias Nice. Can you perhaps share your thinking and your planned approach here?

SanderElias commented 9 years ago

Sure, I'm largely done, just have to leave in a while, perhaps I can finish up on Monday. step 1, adapt the scss, so the colors are exposed to begin with. (done) step 2, write a js-helper to make a dynamic style-sheet so the colors of the selected theme are available under generic names. (mostly done)

you need 2, because a application might switch themes during runtime.

WillsB3 commented 9 years ago

Isn't step 2 covered by angular-materials built in md-theme-watch directive?

Please excuse me if I'm getting confused here :+1:

SanderElias commented 9 years ago

@WillsB3 No, if you want to have an generic class like md-fg-color-50, that needs to be adapted when you switch to a different theme.

I have an working version now. It needs to be hooked up into the ng-material, overthinking what the best way is, to do just that.

plato-cambrian commented 9 years ago

@SanderElias @rschmukler my first thought is:

//jade syntax:
body(md-theme="pink")
  h1.md-fg-color-50 This H1 should be pink
  div(md-theme="light-blue")
    h2.md-fg-color-50 This H2 should be blue

//css
*[md-theme="light-blue"] .md-fg-color-50 {
  color: #03a9f4;
}

*[md-theme="light-blue"] .md-fg-color-60 {
  color: #039be5;
}

*[md-theme="pink"] .md-fg-color-50 {
  color: #e91e63;
}

*[md-theme="pink"] .md-fg-color-60 {
  color: #d81b60;
}

This fails with nested themes, depending on the order of the CSS rules in the source. I don't know the CSS cascade well enough to propose an alternative. In case any CSS wizards have solutions,

Here's a fiddle with this code

SanderElias commented 9 years ago

@plato-cambrian Yeah, I have been considering that too, but as you said, it fails with nested themes. Plus it will generate a lot of wildcard CSS rules. CSS is pretty fast now, but a shipload of *[].xxx will bring performance down on all browsers.

That is why I opted for generating an dynamic style-sheet with JavaScript. A small cost when switching themes, none for the rest of the time.

plato-cambrian commented 9 years ago

@SanderElias i believe you should plan for per-element themes as per https://material.angularjs.org/#/Theming/04_how_it_works So at one point in the dom .md-primary-50 should set color: pink and at another point it should set color: blue.

I don't know if we need to support arbitrary depth nested themes for these convenience classes. The material spec seems to say no. So, working under the assumption that we two nested themes is adequate, I updated the fiddle with a pure CSS solution. (I don't know if the attribute selectors I'm using count as wildcards.)

Two nested themes, main and sub, would fulfil your use case - choose your main theme (three primary tints and one secondary) per customer. Set body[md-theme="customer-theme"]. When you need to use one of your highlight colors, do span[md-theme="warning"].

For the record I think that for your use case you should only use one theme, and set the highlight colors with classes.

PS if this was scrum we would split this issue into two stories: 1) Make convenience classes that set appropriate theme tints on different DOM elements; 2) Define default highlight colors/themes for warning, error, success

SanderElias commented 9 years ago

@plato, hmm, I have to think it over. Im in transit to the the gdgDevfest right now, probably will not behind my computer until monday.

your solution would indeed work, but it will generate a lot of extra css rules. I'll check the growth of the templates, when I'm back at my desk.

It might be a nice solution for the generic classes too.

I'll will come back to you! Op 8 nov. 2014 06:26 schreef "plato" notifications@github.com:

@SanderElias https://github.com/SanderElias i believe you should plan for per-element themes as per https://material.angularjs.org/#/Theming/04_how_it_works So at one point in the dom .md-primary-50 should set color: pink and at another point it should set color: blue.

I don't know if we need to support arbitrary depth nested themes for these convenience classes. The material spec seems to say no. So, working under the assumption that we two nested themes is adequate, I updated the fiddle with a pure CSS solution http://jsfiddle.net/750fqLr7/2/. (I don't know if the attribute selectors I'm using count as wildcards.)

Two nested themes, main and sub, would fulfil your use case - choose your main theme (three primary tints and one secondary) per customer. Set body[md-theme="customer-theme"]. When you need to use one of your highlight colors, do span[md-theme="warning"].

For the record I think that for your use case you should only use one theme, and set the highlight colors with classes.

PS if this was scrum we would split this issue into two stories: 1) Make convenience classes that set appropriate theme tints on different DOM elements; 2) Define default highlight colors/themes for warning, error, success

— Reply to this email directly or view it on GitHub https://github.com/angular/material/issues/537#issuecomment-62246542.

ajoslin commented 9 years ago

@ryanschmukler and I talked about this yesterday... We think we're going to include one more color per theme, called the accent color, as well as three additional hues available per color via classes (probably named hue-1 hue-2 hue-3).

This will allow a custom theme to potentially have 10+ different colors, if you set the hues. On Sat, Nov 8, 2014 at 00:54 Sander Elias notifications@github.com wrote:

@plato, hmm, I have to think it over. Im in transit to the the gdgDevfest right now, probably will not behind my computer until monday.

your solution would indeed work, but it will generate a lot of extra css rules. I'll check the growth of the templates, when I'm back at my desk.

It might be a nice solution for the generic classes too.

I'll will come back to you! Op 8 nov. 2014 06:26 schreef "plato" notifications@github.com:

@SanderElias https://github.com/SanderElias i believe you should plan for per-element themes as per https://material.angularjs.org/#/Theming/04_how_it_works So at one point in the dom .md-primary-50 should set color: pink and at another point it should set color: blue.

I don't know if we need to support arbitrary depth nested themes for these convenience classes. The material spec seems to say no. So, working under the assumption that we two nested themes is adequate, I updated the fiddle with a pure CSS solution http://jsfiddle.net/750fqLr7/2/. (I don't know if the attribute selectors I'm using count as wildcards.)

Two nested themes, main and sub, would fulfil your use case - choose your main theme (three primary tints and one secondary) per customer. Set body[md-theme="customer-theme"]. When you need to use one of your highlight colors, do span[md-theme="warning"].

For the record I think that for your use case you should only use one theme, and set the highlight colors with classes.

PS if this was scrum we would split this issue into two stories: 1) Make convenience classes that set appropriate theme tints on different DOM elements; 2) Define default highlight colors/themes for warning, error, success

— Reply to this email directly or view it on GitHub https://github.com/angular/material/issues/537#issuecomment-62246542.

— Reply to this email directly or view it on GitHub https://github.com/angular/material/issues/537#issuecomment-62249532.

SanderElias commented 9 years ago

@ajoslin, That sound good! Meanwhile I think I have an better idea about how to convey the states to the user.
Namely using the aria states that are available. Something like this: md.theme.xxx[aria-invalid] { //setting for validation error }

.md-theme.xxx[aria-alert] { //settings for warning/danger }

Etc.. If we implement all statuses as aria roles, out apps become instant accessible.

SanderElias commented 9 years ago

~~Oh, I used a small part of sass to generate the colors as in the sample of @plato-cambrian like this:~~

[md-theme="#{$theme-name}"] {
  @each $_myColor in map-keys($primary-color-palette) {
      &.md-fg-#{$_myColor} { color: map-get($primary-color-palette, $_myColor) }
      &.md-bg-#{$_myColor} { background-color: map-get($primary-color-palette, $_myColor) }}
}

The growth of the files isn't a issue in my eyes. approx 1.5Kb pro theme.

After some experimenting, this turned out to be very flaky. I'm not sure if this can be done with an css-only option. However I'm not a crack at css.

plato-cambrian commented 9 years ago

+1 to styling off the aria tags! That's a great idea, it could: • increase aria awareness and use • standardize material status/state notifications in an aria compatible way

On Mon, Nov 10, 2014 at 3:03 AM, Sander Elias notifications@github.com wrote:

Oh, I used a small part of sass to generate the colors as in the sample of @plato-cambrian https://github.com/plato-cambrian like this:

[md-theme="#{$theme-name}"] { @each $_myColor in map-keys($primary-color-palette) { &.md-fg-#{$_myColor} { color: map-get($primary-color-palette, $_myColor) } &.md-bg-#{$_myColor} { background-color: map-get($primary-color-palette, $_myColor) }} }

The growth of the files isn't a issue in my eyes. approx 1.5Kb pro theme.

— Reply to this email directly or view it on GitHub https://github.com/angular/material/issues/537#issuecomment-62357271.

SanderElias commented 9 years ago

I did created this color-switcher proof of concept that works with an dynamic generated style-sheet. Is something like this, a solution that would be considered for inclusion?

I now just generate the colors, but of coarse it can also be used for all additional colors to convey state to the end-user.

marcysutton commented 9 years ago

+1 for styling off of ARIA attributes. Thanks for highlighting this issue!

gkalpak commented 9 years ago

I am not much of a designer, but styling based on ARIA attributes just seems very wrong to me. It couples two totally unrelated things with very orthogonal concerns/requirements, so we are just creating some nice headaches for our future selves. A: "This and that style are not applied timely; this makes transitions look uncoordinated. How do we fix this ?" B: "Aha ! Just need to modify the ngAria module." A: "...!?"

I am definitely pro finding ways to increase ARIA awareness and encourage a11y, but this is not the right way (imo).

So, it's :-1: from me...

(Just to be clear: The -1 is for the specific idea, not the effort people (both from the team and the community) are putting into this, which is plain awesome !)

rschmukler commented 9 years ago

@gkalpak thanks for the input! I'm not sure which way we will end up going with it, but the community should never be afraid to express its opinions - ultimately we are trying to build the best framework possible and getting as many thoughts as possible helps us make informed decisions. Thanks again for the thoughts!

rschmukler commented 9 years ago

@SanderElias @plato-cambrian @WillsB3 @ThomasBurleson @robertmesserle @marcysutton @ajoslin here is a proposal syntax for theming.

Basically, we would use the CSS trick that @SanderElias came up with to provide default palettes via CSS (all of them) and then encourage sticking to a few hues within a palette (as per the material design spec) within a given theme. We use the $mdThemingProvider to configure multiple hues and palettes within a category of actions (eg. primary, accent, warn, etc.) within a theme. $mdThemingProvider can also be used to create multiple themes, but that feature would be less used within this new proposal.

epelc commented 9 years ago

I also agree with @gkalpak I'm all for aria but I don't think it should be used for themes.

marcysutton commented 9 years ago

There is also the issue that some ARIA attributes injected by ngAria can be disabled (such as aria-invalid), making the CSS less stable.

rschmukler commented 9 years ago

JS based theming implemented in 0.7.0 - let us know what you think guys!

klaszlo commented 9 years ago

@rschmukler: The theme colors available only within <md-*> element. Is this expected?

I would expect css rules available which only defines the colors. Something like this: .md-THEME_NAME-fg-400 { color: #29b6f6; } .md-THEME_NAME-bg-400 { background-color: #29b6f6; }

The same for 400,500,600,700,800,900,A100,A200,A400,A700.

The main usecase would be readily available theme colors outside of <md-*> elements.

ilanbiala commented 9 years ago

If what @klaszlo is saying is correct, then it would be great to make the necessary changes so it works outside of md elements.

SanderElias commented 9 years ago

@rschmukler, as @klaszlo is saying, it only works inside (selected) <md-*> elements. We need a solution so that the colors are available outside those elements too. And under a generic name too. and example:

   <div class='md-hue1'>Hues are for <span class='md-accent'>backgrounds</span> right?</div>

This should be colored according to the selected theme! In my tests this does not.

slaivyn commented 9 years ago

:+1: I need that too :) how can I set a div background to "md-primary md-hue1" without hardcoding the value in the CSS file?

Edit: don't need any more because I switched to Materialize. Maybe angular-material could integrate Materialize to benefit of all the work done there.

opraatnitt commented 9 years ago

I am new for Material design. Can anyone explain to me how i will change my default theme to someother.

Thanks in advance

epelc commented 9 years ago

@opraatnitt add md-theme="otherTheme" to any element to change its theme. It should be mentioned in the theme docs or under directives of you need more info.

mbitson commented 9 years ago

I'm a little behind here, but I believe that this is the wrong approach. If you want 'functional' colors, such as one to warn users, don't modify the css for the current theme- just apply a 'warning' theme to that particular element. This allows you to pick any hue of your warning theme to ensure your contrast on the page, as well as chose a secondary palette just in case you need some dark warnings and some light. If creating the themes is taking too long, you could create many angularJS material design themes easily using this tool I created before: https://github.com/mbitson/mcg

Cheers!