Components: Cannot apply an alternate theme specifically to the md-sidenav element

Created on 1 May 2017  路  6Comments  路  Source: angular/components

Bug, feature request, or proposal:

Feature request

What is the expected behavior?

Applying the 'dark-theme' to a sidenav or other specific elements should work. Sometimes you want only a sidenav or specific sections of a page with an alternate theme.

What is the current behavior?

Creating a theme and then applying it to sidenav affects children of the sidenav but not the sidenav itself. So text within md-list-item turns white but the background of the sidenav remains white also.

What are the steps to reproduce?

http://plnkr.co/edit/R7lhJkgurw4nNhUJ2BQ7?p=preview

A workaround is in the plunkr. To see the work around in app.component.html, toggle the class on the md-sidenav between "dark-theme" to see the issue or "dark-sidenav" for the workaround as it should appear. The styles for both are in app.theme.scss. app.theme.scss is the output of the material _theming.scss with my additions for my themes at the end.

What is the use-case or motivation for changing an existing behavior?

I've had cases with 2 side navs. The outer one is the site navigation, while the inner is page specific with a list of items to be edited, where clicking one switches the edit form to the selected item. To visually separate the navs, I make the outer nav dark and default to auto-hide unless the user pins it.

Which versions of Angular, Material, OS, browsers are affected?

latest Angular, and Angular Material per systemjs config of the plunkr. For the Material theming code, I copied from master (today).
npm install --save https://github.com/angular/material2-builds.git

I copied the results of _theming.scss from this build into the plunkr.

Is there anything else we should know?

Thanks for the great work!

P3 materiasidenav theming

Most helpful comment

The following workaround worked for me ( inspired by the .mat-app-background class here: https://github.com/angular/material2/blob/master/src/lib/core/_core.scss )

In styles.scss:

// Define an alternate dark theme.
$the-dark-theme: mat-dark-theme($my-app-primary, $my-app-accent, $my-app-warn);

.the-dark-theme {
    @include angular-material-theme($the-dark-theme);
    $background: map-get($the-dark-theme, background);
    background-color: mat-color($background, background);
}

Then I can apply a dark theme to my sidenav only by adding .the-dark-theme class:

<mat-sidenav #mainmenu class="the-dark-theme">
  Everything in here will be dark theme
</mat-sidenav>

All 6 comments

You can create alternate themes scoped to whatever arbitrary selector you like, and then apply that select to whichever subsection of your app fits your needs.

Can you elaborate on what you mean? I tried what is in the documentation, and it does not work. I had to create another in more depth style to replicate material sass code.

Here is what is documented that I tried first:

@include mat-core();
$app-color-primary: mat-palette($mat-light-blue);
$app-color-accent: mat-palette($mat-amber);
$color-app-warn:    mat-palette($mat-red);
$app-theme: mat-light-theme($app-color-primary, $app-color-accent, $color-app-warn);

@include angular-material-theme($app-theme);

.dark-theme {
  $dark-primary: mat-palette($mat-indigo);
  $dark-accent: mat-palette($mat-brown);

  $dark-theme: mat-dark-theme($dark-primary, $dark-accent);

  @include angular-material-theme($dark-theme);
}

When this 'dark-theme' class is applied at the root of the document the whole page does get the dark theme. If I instead apply the class at the md-sidenav component, the sidebar is not dark theme, but only it's children are (the menu items). But since the background is at the sidenav level, the background of the sidenav doesn't change to dark.

The workaround solution to the problem seems to be to replicate what is in the material scss code to build this 'dark-sidenav' class (seen in the plunkr). What I am suggesting is that this should not be needed if the material scss applied to the element it was on.

For instance, look at this code in the the original material scss.

@mixin mat-sidenav-theme($theme) {
  $primary: map-get($theme, primary);
  $accent: map-get($theme, accent);
  $warn: map-get($theme, warn);
  $background: map-get($theme, background);
  $foreground: map-get($theme, foreground);

  // We use invert() here to have the darken the background color expected to be used. If the
  // background is light, we use a dark backdrop. If the background is dark, 
  // we use a light backdrop.
  $sidenav-backdrop-color: invert(mat-color($background, card, 0.6)) !default;
  $sidenav-background-color: mat-color($background, dialog) !default;
  $sidenav-container-background-color:  mat-color($background, background) !default;
  $sidenav-push-background-color: mat-color($background, dialog) !default;

  .mat-sidenav-container {
    background-color: $sidenav-container-background-color;
    color: mat-color($foreground, text);
  }

  .mat-sidenav {
    background-color: $sidenav-background-color;
    color: mat-color($foreground, text);

    &.mat-sidenav-push {
      background-color: $sidenav-push-background-color;
    }
  }

  .mat-sidenav-backdrop.mat-sidenav-shown {
    background-color: $sidenav-backdrop-color;
  }
}

Notice this part specifically:

.mat-sidenav {
    background-color: $sidenav-background-color;
    color: mat-color($foreground, text);
    //...
  }

The sample at the start of this comment, and documented in material as how to create a theme, would work if it referenced the parent selector

&.mat-sidenav, .mat-sidenav {
    background-color: $sidenav-background-color;
    color: mat-color($foreground, text);
    //..
  }

This revision works with the dark-theme class applied at the top of the document to style the whole page, or at the md-sidenav level to style just the sidenav. Of course, this would also need to be done in all the other mixins. Can a change like this be made?

I see what you mean now. The issue is that you can't add an arbitrary parent element to the sidenav.

@mmalerba thoughts?

I'm having same issue, our sidenav supposes to use another theme with the rest of the app but I cannot find a way to overcome this limitation.

The following workaround worked for me ( inspired by the .mat-app-background class here: https://github.com/angular/material2/blob/master/src/lib/core/_core.scss )

In styles.scss:

// Define an alternate dark theme.
$the-dark-theme: mat-dark-theme($my-app-primary, $my-app-accent, $my-app-warn);

.the-dark-theme {
    @include angular-material-theme($the-dark-theme);
    $background: map-get($the-dark-theme, background);
    background-color: mat-color($background, background);
}

Then I can apply a dark theme to my sidenav only by adding .the-dark-theme class:

<mat-sidenav #mainmenu class="the-dark-theme">
  Everything in here will be dark theme
</mat-sidenav>

Not sure if it's entirely related but one thing I'm wondering is who decides which components have the CanColor mixin?

If you use the nav schematic then you're given a layout using a sidenav and toolbar that's fixed to the top. The toolbar supports color="primary" but the sidenav does not:

<mat-sidenav-container>
  <mat-sidenav color="primary"></mat-sidenav>
  <mat-sidenav-content>
    <mat-toolbar color="accent"></mat-toolbar>
    <router-outlet></router-outlet>
  </mat-sidenav-content>
</mat-sidenav-container>

Another thing is that the sidenav theme piggy-backs off of the dialog background: https://github.com/angular/material2/blob/f4d0ab58d7ab096a950ab6833e48c31c710e6330/src/lib/sidenav/_sidenav-theme.scss#L13

Should sidenav:
1) Support the color property?
2) Have it's own place inside the palette?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

LoganDupont picture LoganDupont  路  3Comments

alanpurple picture alanpurple  路  3Comments

RoxKilly picture RoxKilly  路  3Comments

jelbourn picture jelbourn  路  3Comments

3mp3ri0r picture 3mp3ri0r  路  3Comments