Flash
Flash

Reputation: 1014

Changing Rotation of Mat Expansion Indicator

I was successfully able to move the mat Indicator to the left, instead of the right and I used the transform attribute to make it turn inward when expanding. However I want the indicator to face upward when expanded and downward when collapsed. How do I properly style it to achieve this: https://stackblitz.com/edit/indicatorrotation?file=styles.css

expansion-overview-example.css

  .mat-expansion-panel-header {
       flex-direction: row-reverse;
   } 

Global styles.css

  .mat-expansion-indicator::after {
      transform: rotate(225deg) !important;  
}

Upvotes: 3

Views: 9165

Answers (3)

snowlight
snowlight

Reputation: 35

Thanks Ivan, Actually, you only need this (no need to disable animations) (I know ng-deep is deprecated) :

:host ::ng-deep .mat-expansion-panel {
  .mat-expansion-indicator {

    &::after {
      transform: rotate(-135deg) !important;
    }
  }

  &.mat-expanded {
    .mat-expansion-indicator {
      transform: rotate(180deg) !important;
    }
  }
}

Upvotes: 3

Ivan  Zagainov
Ivan Zagainov

Reputation: 560

Disable default animation:

<mat-expansion-panel-header [@.disabled]="true">

Rewrite styles in some global styles.scss

  .mat-expansion-panel {
    .mat-expansion-indicator {
      transition: transform .3s ease;

      &::after {
        transform: rotate(-135deg);
      }
    }

    &.mat-expanded {
      .mat-expansion-indicator {
        transform: rotate(40deg) !important;
      }
    }
  }

Upvotes: 6

ysf
ysf

Reputation: 4864

mat expansion indicator's rotation is handled by this animation. as it can be seen there it is straightforward rotate(180deg) (180deg clockwise). and indicator initially has rotate(45deg) which show downward icon by default when panel is closed and upward icon when panel is open with clockwise animation.

when you apply rotation with;

.mat-expansion-indicator::after {
    transform: rotate(225deg) !important;  
}

icon is rotated upwards initially when panel is closed, when clicked it is rotated by 180deg clockwise. at this point you cannot show downwards icon when closed and upwards when open because of rotate(225deg) if you change that you loose inward turning because animation starts clockwise, but we need exactly the opposite.

eventually it is not possible to have counter-clockwise rotation without overriding default animation. Unfortunately, Angular Material doesn't have any mechanism to override default animations, as seen here .

so my solution is to completely disable default animations on mat-expansion-panel-header and implement a custom directive that imitates this animation but counter-clockwise.

first disable default animation on mat-expansion-panel-header;

<mat-expansion-panel-header [@.disabled]="true">

then create new animations in styles.css with same timing and behavior as default animation.

@keyframes inwards-open {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(-135deg); }
}

@keyframes inwards-close {
  0%   { transform: rotate(-135deg); }
  100% { transform: rotate(0deg); }
}

.openAnimate {
  animation: inwards-open 225ms cubic-bezier(0.4,0.0,0.2,1) !important;
}

.closeAnimate {
  animation: inwards-close 225ms cubic-bezier(0.4,0.0,0.2,1) !important;
}

and implement a custom directive that handles animation status based on panel open/close events

import { Directive, ElementRef, HostListener, AfterViewInit, OnDestroy } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';

@Directive({
  selector: '[appCustomMatExpansionToggle]'
})
export class CustomMatExpansionToggleDirective implements AfterViewInit, OnDestroy {
  private elem: HTMLSpanElement;
  private uns: Subscription;
  constructor(private elRef: ElementRef) {}

  ngAfterViewInit() {
    this.elem = this.elRef.nativeElement.querySelector(".mat-expansion-indicator");

    this.uns = fromEvent(this.elem, 'animationend').subscribe(() => {
      this.elem.classList.remove("openAnimate");
      this.elem.classList.remove("closeAnimate");
    });
  }

  @HostListener("opened")
  onOpen() {
    this.elem.classList.add("openAnimate");
  }

  @HostListener("closed")
  onClose() {
    this.elem.classList.add("closeAnimate");
  }

  ngOnDestroy() {
    this.uns.unsubscribe();
  }
}

and finally apply the custom directive to mat-expansion-panel

<mat-expansion-panel appCustomMatExpansionToggle>

here is a working demo https://stackblitz.com/edit/indicatorrotation-mp73uh

Upvotes: 9

Related Questions