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

Navigation drawer - Mini variant behavior #1728

Open
Daugoh opened this issue Nov 4, 2016 · 103 comments
Open

Navigation drawer - Mini variant behavior #1728

Daugoh opened this issue Nov 4, 2016 · 103 comments
Labels
area: material/sidenav feature This issue represents a new feature or feature request rather than a bug or bug fix P5 The team acknowledges the request but does not plan to address it, it remains open for discussion

Comments

@Daugoh
Copy link

Daugoh commented Nov 4, 2016

Feature request:

Add the "Mini variant" behavior of the Navigation drawer.
As defined in the Google Material guidelines:
https://material.google.com/patterns/navigation-drawer.html#navigation-drawer-behavior

What is the expected behavior?

When toggled, the navigation drawer change its width.
It's not fully hidden.

What is the current behavior?

Only two states are available: displayed, hidden

What are the steps to reproduce?

Create a sidenav and toggle it on and off.
The sidenav can only be opened or closed.
No intermediate state.

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

Desktop users need to quickly change the current view.
The sliding effect of the sidenav could be annoying when used a lot.
It's common for desktop apps to keep the navigation opened by default.
But in some cases the icons are self explanatory so no need to display the associated labels.

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

Angular2

Is there anything else we should know?

A similar feature request was submitted for Angular 1:
angular/material#3158

@jelbourn
Copy link
Member

jelbourn commented Nov 9, 2016

Is there any reason you couldn't control the width of the sidenav with css and toggle classes based on which width you want to display?

@jelbourn jelbourn added feature This issue represents a new feature or feature request rather than a bug or bug fix P5 The team acknowledges the request but does not plan to address it, it remains open for discussion labels Nov 9, 2016
@Daugoh
Copy link
Author

Daugoh commented Nov 14, 2016

Hello @jelbourn

Thanks for your answer.

Yes I tried to do it manually.
I can show/hide the texts with a CSS class or use a ngIf.
It works but then I have a problem of alignment for my icons.
They are not correctly centered.

So yes we can do it ourselves but I think it would be really useful to have it natively.
And then just use an attribute like textVisible or iconOnly for instance ...

Regards

@kuncevic
Copy link
Contributor

kuncevic commented Dec 15, 2016

Is that feature has being planned yet? Is there any deadlines on that?

@Daugoh have you come up with any proper soulution for this one?

Here is #2021 one of the ways http://plnkr.co/edit/LcRDIHNFjHKLFTaMdNEM?p=preview of doing that

@MrNikunjPatel
Copy link

Probably, You can manage it buy css for intermediate state as below. You might need some css overrides as per need.

<md-sidenav-layout fullscreen> <md-sidenav #sidenav> <md-nav-list> <a md-list-item (click)="sidenav.toggle()"> <md-icon md-list-icon>menu</md-icon> </a> <a md-list-item *ngFor="let view of views"> <md-icon md-list-icon>{{view.icon}}</md-icon> <span md-line>{{view.name}}</span> </a> </md-nav-list> </md-sidenav> <app-contacts></app-contacts> </md-sidenav-layout>

/*left sidenav style override*/ md-sidenav { background-color: #f8921e; overflow: hidden; } md-nav-list a[md-list-item] { color: #fff; } md-nav-list a[md-list-item] .md-list-item{ padding: 0 10px !important; } .md-sidenav-over.md-sidenav-closed md-nav-list a[md-list-item] .md-list-text { display: none !important; } md-sidenav.md-sidenav-closed { transform: translate3d(0, 0, 0) !important; visibility: visible !important; min-width: 40px !important; }

@Daugoh
Copy link
Author

Daugoh commented Jan 9, 2017

@kuncevic
So far I'm just using a quick workaround with a ngIf to show/hide the text

@vtolstov
Copy link

Any news?

@vtolstov
Copy link

@rajamarketing can you help me and provide css with @media query so i don't need to watch in angular componnet for window resize events and css applied automatic?

@brunoracosta
Copy link

Hi people, news?

@Stoom
Copy link

Stoom commented Jun 12, 2017

from @rajamarketing comment here is what I've come up with, be it sass complains but it compiles...

    md-sidenav {
        width: 200px;

        md-icon {
            padding-right: 20px !important;
        }

        &.mat-sidenav-closed {
            transform: translate3d(0, 0, 0) !important; 
            visibility: visible !important;
            min-width: 64px !important;
            width: 64px !important;

            &~ /deep/.mat-sidenav-content {
                margin-left: 64px !important;
            }
        }
    }
}

@unstephenk
Copy link

Any updates?

@JanOschii
Copy link

Seems like @daxsom has a solution.
Any chance to get this with the next stable release?

@Misiu
Copy link

Misiu commented Sep 4, 2017

firebase and google analytics has this functionality.
It would be awesome to have this build in and working by default

@rui-cruz
Copy link

yes pls!

@Ravi-Rajpurohit
Copy link

this may help ..
https://github.com/Ravi-Rajpurohit/mini-md-sidenav

@liri2006
Copy link

liri2006 commented Oct 11, 2017

Would be extremely helpful to have this as a native feature. As for now it requires some hacky css to make it work both for desktop (mini-sidenav) and mobile (classic one), which are breaking with almost every release :)

@matte00
Copy link

matte00 commented Nov 15, 2017

Any news?

@haskelcurry
Copy link

Yes, any news, please?

@morten-kirstein
Copy link

could be on the steps. I mentioned it to Thomas Burleson from the Angular Material team at Angular Connect. He said it shouldn't take long to make. Meanwhile, we could use the CSS hack method.

I'll just follow up on it.

@51Ray
Copy link

51Ray commented Nov 21, 2017

I hope and expect...

@AyushiSrivastava20
Copy link

any stable release with these changes?

@Melanie-M
Copy link

Thanks to #8488 you can now use autosize in mat-sidenav-container, so you can resize the sidenav without css hacks.

Here's an example adapted from the "autosize sidenav" example:
https://stackblitz.com/edit/angular-b4gmby

@mackelito
Copy link

@Melanie-M so just a question... If a remove "autosize"... I still see the same result?

@Melanie-M
Copy link

@mackelito I think without autosize the main content doesn't resize properly, the sidenav overlaps it instead. But so depending on what behavior you want, I guess it can work without autosize

@Jordan-Hall
Copy link

@maxisam created the NPM package https://www.npmjs.com/package/angular-material-rail-drawer
Repo here https://github.com/Jordan-Hall/angular-material-rail-drawer-plugin

Any issues please let me know. I've just picked up next blog I need to write and a small freelance role then I'll hopefully have a PR ready for here

@KaranPato
Copy link

Tried that but getting the below issue. @Jordan-Hall

error TS2322: Type '"rail"' is not assignable to type 'MatDrawerMode'.
<mat-sidenav #appDrawer mode="rail" opened="true">

@Ravi-Rajpurohit
Copy link

this may help ..
https://github.com/Ravi-Rajpurohit/mini-md-sidenav

@KaranPato duniya gol hai mere bhai.

@KaranPato
Copy link

KaranPato commented Sep 10, 2021

I am able to implement what you have implemented @Ravi-Rajpurohit, it's just the transition is not there which you can see here

https://stackblitz.com/edit/angular-material-mini-variant

@anymos
Copy link

anymos commented Jul 25, 2022

any news on this ? years after ....

@Jordan-Hall
Copy link

@anymos Last i heard the scope for rail has been considerably .

@serkon
Copy link

serkon commented Jul 30, 2022

I created an example based on scss. Maybe someone can help to create the mobile version according to this sample.

  • Step 1:
    styles.scss
// src/styles.scss
:root {
  --menu-width-open: 200px;
  --menu-width-closed: 64px;
}

.mat-drawer-container {
  .mat-drawer {
    box-sizing: content-box;
    width: var(--menu-width-open);
    transition: all 0.3s ease-in-out !important;
  }

  .mat-drawer-content {
    // transform: translateX(200px);
    margin-left: var(--menu-width-open) !important;
    transition: all 0.3s ease-in-out !important;
  }

  &.container-closed {
    .mat-drawer {
      width: var(--menu-width-closed);
    }

    .mat-drawer-content {
      // transform: translateX(64px) !important;
      margin-left: var(--menu-width-closed) !important;
    }
  }
}
  • Step 2:
    app.componenet.html
    Add: [ngClass]="{ 'container-closed': !isExpanded }" to mat-drawer-container
<mat-drawer-container class="example-container" autosize [ngClass]="{ 'container-closed': !isExpanded }">
  <mat-drawer #drawer class="example-sidenav" mode="side" disableClose="true" opened="true">
    <button (click)="isExpanded = !isExpanded" mat-raised-button>click</button>
  </mat-drawer>
  <div class="example-sidenav-content">
    <router-outlet></router-outlet>
    <button type="button" mat-button (click)="drawer.toggle()">Toggle sidenav</button>
  </div>
</mat-drawer-container>
  • Step 3:
    app.component.ts
    And add isExpanded = false; to app.component.ts file.
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  isExpanded = false;
}

@Jordan-Hall
Copy link

@serkon have you taken a look at this one I've done https://github.com/Jordan-Hall/angular-material-rail-drawer-plugin

@serkon
Copy link

serkon commented Jul 31, 2022

@serkon have you taken a look at this one I've done https://github.com/Jordan-Hall/angular-material-rail-drawer-plugin

Hi Jordan, thanks for suggestion. I have tried yesterday. It was not worked for me. I have used Angular Metarial Latest, and get error about 'rail' directive. It say that it's not an acceptable key by the "mat-sidenav". Maybe it was my fault or check please again maybe there are an error.

So, I decided to forward with my own solution.

@lramondev
Copy link

I gave up and made my own drawer

@bergamin
Copy link

bergamin commented Aug 1, 2022

@lramondev, same here. We use material design for most of our common components, but this one we had to fully develop in 2019 because of this missing feature. We are still waiting for it though. One less thing for us to maintain

@nzbin
Copy link

nzbin commented Oct 21, 2022

@anymos @Jordan-Hall @serkon @lramondev @bergamin
Hi guys, maybe you can try the ng-matero. It's a Material admin framework and fully responsive.
Online demo: https://ng-matero.github.io/ng-matero/

@mackelito
Copy link

@anymos @Jordan-Hall @serkon @lramondev @bergamin
Hi guys, maybe you can try the ng-matero. It's a Material admin framework and fully responsive.
Online demo: https://ng-matero.github.io/ng-matero/

Are you really suggesting that they use this admin template when all they requested is a freature on the drawer/sidebar? 🤯

@bergamin
Copy link

Hi guys, maybe you can try the ng-matero. It's a Material admin framework and fully responsive.
Online demo: https://ng-matero.github.io/ng-matero/

I checked the demo and your lib is pretty cool. Unfortunately, we have a great deal of apps to maintain and keep standardised, so the less UX libraries the better. For this specific issue, we ended up designing our own sidenav and it's too big now to move elsewhere.

This issue made us rethink our design strategies, so we invested in UX and we are now building our own design library. We are slowly moving our Material use to this new library we are building.

@ericute
Copy link

ericute commented May 5, 2023

@Jordan-Hall any luck getting your PR (#20050) merged?

@Jordan-Hall
Copy link

@Jordan-Hall any luck getting your PR (#20050) merged?

Nope :( rejected because they no "clear" spec even though i based it on the spec and because they not sure which approach there want to go

@Salomeleshka
Copy link

@Jordan-Hall is there a compatible version of the Rail Drawer plugin to angular 13?

@Jordan-Hall
Copy link

Do not believe so. If they is I can get you the version number you required. I built this before before 13 and been migrated to every very since

@Salomeleshka
Copy link

@Jordan-Hall angular v 13.1.3

@StephGoode
Copy link

Hi @Jordan-Hall, I'm also looking to use this plugin with Angular 13. Please let us know if this is possible!

@lramondev
Copy link

I waited for this feature for a long time until I developed my solution. Don't wait for the angular team to resolve this issue.

@Jordan-Hall
Copy link

Jordan-Hall commented Jun 21, 2023

@Salomeleshka @StephGoode 1.1.4 is supported for angular 13.

Been upgrading this for 3 years, will likely go through the rail spec again to check its still to standard. But COME ON ANGULAR this has been on people wish list since 2016. But never mind, we get a really new cool looking control flow that no one really asked for. But features to help devs and companies are not a priority

@kshitiz-goel07
Copy link

I want to create a side navber like this one , How can I do so ?
I want the navbar to open and collapse ( while showing icons )

@IvanAmdaris
Copy link

IvanAmdaris commented Sep 19, 2023

I know this maybe is a late response, but here is how I did it with Tailwind and some scss ( Angular 15 ).

Add the scss below into your scss file of the sidebar ( no need to add root scss ):

.drawer {
  width: 6.375rem; // Closed width - adjust as needed
  transition: all 0.3s ease-in-out !important;
  transform: translate(0px);

  &-opened {
    width: 14.375rem;  // Opened width - adjust as needed
    transition: all 0.3s ease-in-out !important;
  }
}

In your html mat-drawer element should look like this:

  <mat-drawer
    mode="over"
    #drawer
    closed
    class="overflow-visible block visible"
    [ngClass]="{
      drawer: !drawer.opened
      'drawer-opened': drawer.opened
    }"
  > 

That should be enough for the animation. Align your icons and text like this ( adjust margin as needed or add buttons, it will be the same ) :

<div class="flex">
      <div>
        <mat-icon class="ml-10">
            heart
        </mat-icon>
      </div>
      <div class="ml-8">
            Menu Item
      </div>
</div>

The button to toggle this menu should call drawer.toggle(). Wherever you decide to put your button:

(click)="drawer.toggle()"

@brayansi
Copy link

brayansi commented Apr 15, 2024

Sidenav Responsive Mobile/Desktop

  <mat-drawer-container class="container">
    <mat-drawer class="sidenav-menu" [ngClass]="{ 'sidenav-menu-desktop': !isMobileSidenav, 'sidenav-menu-half': isHalfSidenav }">
      <p>Auto-resizing sidenav</p>
    </mat-drawer>

    <mat-drawer-content>
      <div class="sidenav-content">
        <mat-card appearance="outlined">
          <mat-card-content>
            <button type="button" mat-button (click)="open()">Toggle sidenav</button>
          </mat-card-content>
        </mat-card>
      </div>
    </mat-drawer-content>
  </mat-drawer-container>
.container {
  height: 100vh;
}

.sidenav-menu {
  padding: 16px;
  width: 270px;
}

.sidenav-menu-desktop {
  transition: all 0.3s ease-in-out;
}

.sidenav-menu-half {
  width: 100px;
}

.sidenav-content {
  display: flex;
  height: 100%;
  align-items: center;
  justify-content: center;
  background-color: #fafafa;
}
import { AfterViewInit, Component, ViewChild, inject } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { MatDrawer, MatDrawerContent, MatSidenavModule } from '@angular/material/sidenav';
import { MatCard, MatCardContent } from '@angular/material/card';
import { BreakpointObserver } from '@angular/cdk/layout';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-layout',
  standalone: true,
  imports: [RouterOutlet, MatSidenavModule, MatCard, MatCardContent, CommonModule],
  templateUrl: './layout.component.html',
  styleUrl: './layout.component.scss',
})
export class LayoutComponent implements AfterViewInit {
  @ViewChild(MatDrawer) sidenav!: MatDrawer;
  @ViewChild(MatDrawerContent) content!: MatDrawerContent;

  protected isMobileSidenav: boolean = false;
  protected isHalfSidenav: boolean = false;

  private readonly breakpointObserver: BreakpointObserver = inject(BreakpointObserver);

  ngAfterViewInit(): void {
    Promise.resolve().then(() => {
      this.breakpointObserver.observe(['(max-width: 800px)']).subscribe((res) => {
        if (this.sidenav) {
          if (res.matches) {
            this.sidenav.mode = 'over';
            this.isMobileSidenav = true;
            this.sidenav.close();
          } else {
            this.sidenav.mode = 'side';
            this.isMobileSidenav = false;
            this.isHalfSidenav = false;
            this.sidenav.open();
          }
        }
      });
    });
  }

  open(): void {
    if (this.isMobileSidenav) {
      this.sidenav.toggle();
    } else {
      this.isHalfSidenav = !this.isHalfSidenav;
      this.content.getElementRef().nativeElement.style.marginLeft = this.isHalfSidenav ? '100px' : '270px';
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: material/sidenav feature This issue represents a new feature or feature request rather than a bug or bug fix P5 The team acknowledges the request but does not plan to address it, it remains open for discussion
Projects
None yet
Development

Successfully merging a pull request may close this issue.