0

I've created a 3-state sidepanel component that provides the following states:

  • Collapsed - Sidepanel is completely hidden
  • Thin - Icon is visible with tooltip
  • Full - Icon and label are visible

The issue I have is that transitions applied via a reveal trigger do not perform easing as defined in their transition functions.

All slide trigger transitions are working as expected, but the reveal trigger just performs the style changes without any easing.

Please see below component definitions and Sample StackBlitz:

SidepanelComponent Template

<mat-nav-list [@slide]="state">
  <panel-link link="/home" [state]="state" label="Home" icon="home"></panel-link>
</mat-nav-list>

SidepanelComponent Definition

import { Component } from '@angular/core';
import { trigger, state, transition, style, animate } from '@angular/animations';
import { SidepanelService } from '../../services/sidepanel.service';

@Component({
  selector: 'sidepanel',
  templateUrl: 'sidepanel.component.html',
  styleUrls: ['sidepanel.component.css'],
  animations: [
    trigger(
      'slide', [
        state('collapse', style({
          width: 0,
          opacity: 0
        })),
        state('thin', style({
          width: '*',
          opacity: 1
        })),
        state('full', style({
          width: '*',
          opacity: 1
        })),
        transition('collapse => thin', animate('500ms ease-out')),
        transition('thin => full', animate('500ms ease-out')),
        transition('full => collapse', animate('500ms ease-in'))
      ]
    )
  ]
})
export class SidepanelComponent {
  private state: string;
  constructor(
    public sidepanel: SidepanelService
  ) {
    sidepanel.state$.subscribe((s: string) => this.state = s);
  }
}

PanelLinkComponent Template

<a mat-list-item [routerLink]="link"
                 routerLinkActive="active"
                 [@slide]="state"
                 [matTooltip]="label"
                 [matTooltipPosition]="tooltipPosition"
                 [matTooltipDisabled]="state !== 'thin'">
  <mat-icon>{{icon}}</mat-icon>
  <span [@reveal]="state">{{label}}</span>
</a>

PanelLinkComponent Definition

import { Component, Input } from '@angular/core';
import { trigger, state, transition, style, animate } from '@angular/animations';

@Component({
  selector: 'panel-link',
  templateUrl: 'panel-link.component.html',
  animations: [
    trigger(
      'slide', [
        state('collapse', style({
          width: 0,
          opacity: 0,
        })),
        state('thin', style({
          width: '*',
          opacity: 1
        })),
        state('full', style({
          width: '*',
          opacity: 1
        })),
        transition('collapse => thin', animate('500ms ease-out')),
        transition('full => collapse', animate('500ms ease-in'))
      ]
    ),
    trigger(
      'reveal', [
        state('collapse', style({
          width: 0,
          opacity: 0,
          'margin-left': 0,
          'margin-right': 0,
        })),
        state('thin', style({
          width: 0,
          opacity: 0,
          'margin-left': 0,
          'margin-right': 0,
        })),
        state('full', style({
          width: '100%',
          opacity: 1,
          'margin-left': '15px',
          'margin-right': '10px',
        })),
        transition('thin => full', animate('500ms ease-out')),
        transition('full => collapse', animate('500ms ease-in'))
      ]
    )
  ]
})
export class PanelLinkComponent {
  @Input() link: string;
  @Input() state = 'thin';
  @Input() label = 'Home';
  @Input() tooltipPosition = 'right';
  @Input() icon = 'home';
}
Jaime Still
  • 1,949
  • 20
  • 31

1 Answers1

0

Ultimately, I ended up removing the reveal trigger and used CSS transitions based on an open / closed state to accomplish what I was trying to do.

PanelLinkComponent Style

a span.closed {
  opacity: 0;
  width: 0;
  margin-left: 0;
  margin-right: 0;
  transition: opacity 100ms, width 100ms, margin-left 100ms, margin-right 100ms;
  transition-timing-function: ease-out;
}

a span.open {
  opacity: 1;
  width: 100%;
  margin-left: 15px;
  margin-right: 10px;
  transition: opacity 100ms, width 100ms, margin-left 100ms, margin-right 100ms;
  transition-timing-function: ease-in;
}

PanelLinkComponent Template

<a mat-list-item [routerLink]="link"
                 routerLinkActive="active"
                 [@slide]="state"
                 [matTooltip]="label"
                 [matTooltipPosition]="tooltipPosition"
                 [matTooltipDisabled]="state !== 'thin'">
  <mat-icon>{{icon}}</mat-icon>
  <span [ngClass]="{'closed': state !== 'full', 'open': state === 'full'}">{{label}}</span>
</a>
Jaime Still
  • 1,949
  • 20
  • 31