Skip to content

Commit 791d2e5

Browse files
committed
fix(button): prevent style flickering on initial render by leveraging '--_ig-init-transition'
1 parent dd5ba17 commit 791d2e5

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

projects/igniteui-angular/src/lib/core/styles/components/button/_button-theme.scss

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@
6161
$variant
6262
);
6363

64-
$button-transition: color $time ease-in-out,
65-
background-color $time ease-in-out,
66-
border-color $time ease-in-out,
67-
box-shadow $time ease-in-out;
64+
$button-transition: color var(--_ig-init-transition, #{$time}) ease-in-out,
65+
background-color var(--_ig-init-transition, #{$time}) ease-in-out,
66+
border-color var(--_ig-init-transition, #{$time}) ease-in-out,
67+
box-shadow var(--_ig-init-transition, #{$time}) ease-in-out;
6868

6969
$button-disabled-shadow: none;
7070

projects/igniteui-angular/src/lib/core/styles/components/icon-button/_icon-button-theme.scss

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@
7373
-webkit-tap-highlight-color: transparent;
7474
overflow: hidden;
7575
white-space: nowrap;
76-
transition: box-shadow .2s ease-in, background .15s ease-out;
77-
transition-delay: .05s;
76+
transition:
77+
box-shadow var(--_ig-init-transition, .2s) ease-in,
78+
background var(--_ig-init-transition, .15s) ease-out;
79+
transition-delay: var(--_ig-init-transition, .05s);
7880
min-width: unset;
7981
min-height: unset;
8082
font-size: rem(24px, 24px);
@@ -95,7 +97,9 @@
9597
}
9698

9799
@if $variant == 'fluent' {
98-
transition: color .15s ease-out, background .15s ease-out;
100+
transition:
101+
color var(--_ig-init-transition, .15s) ease-out,
102+
background var(--_ig-init-transition, .15s) ease-out;
99103

100104
&::after {
101105
position: absolute;
@@ -109,11 +113,18 @@
109113
}
110114

111115
@if $variant == 'bootstrap' {
112-
transition: box-shadow .15s ease-out, color .15s ease-out, background .15s ease-out;
116+
transition:
117+
box-shadow var(--_ig-init-transition, .15s) ease-out,
118+
color var(--_ig-init-transition, .15s) ease-out,
119+
background var(--_ig-init-transition, .15s) ease-out;
113120
}
114121

115122
@if $variant == 'indigo' {
116-
transition: color .15s ease-in-out, box-shadow .15s ease-in-out, background .15s ease-in-out, border-color .15s ease-in-out;
123+
transition:
124+
color var(--_ig-init-transition, .15s) ease-in-out,
125+
box-shadow var(--_ig-init-transition, .15s) ease-in-out,
126+
background var(--_ig-init-transition, .15s) ease-in-out,
127+
border-color var(--_ig-init-transition, .15s) ease-in-out;
117128
}
118129
}
119130

projects/igniteui-angular/src/lib/directives/button/button-base.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { Directive, ElementRef, EventEmitter, HostBinding, HostListener, Input, Output, booleanAttribute } from '@angular/core';
1+
import {
2+
Directive, ElementRef, EventEmitter, HostBinding, HostListener, Input, Output, booleanAttribute, AfterViewInit,
3+
} from '@angular/core';
24

35
export const IgxBaseButtonType = {
46
Flat: 'flat',
@@ -7,7 +9,7 @@ export const IgxBaseButtonType = {
79
} as const;
810

911
@Directive()
10-
export abstract class IgxButtonBaseDirective {
12+
export abstract class IgxButtonBaseDirective implements AfterViewInit {
1113
/**
1214
* Emitted when the button is clicked.
1315
*/
@@ -79,7 +81,14 @@ export abstract class IgxButtonBaseDirective {
7981
return this.disabled || null;
8082
}
8183

82-
constructor(public element: ElementRef) { }
84+
protected constructor(
85+
public element: ElementRef,
86+
) {
87+
// In browser, set via native API for immediate effect (no-op on server).
88+
// In SSR there is no paint, so there’s no visual rendering or transitions to suppress.
89+
// Fix style flickering https://github.com/IgniteUI/igniteui-angular/issues/14759
90+
this.element.nativeElement.style.setProperty('--_ig-init-transition', '0s');
91+
}
8392

8493
/**
8594
* @hidden
@@ -98,4 +107,11 @@ export abstract class IgxButtonBaseDirective {
98107
public get nativeElement() {
99108
return this.element.nativeElement;
100109
}
110+
111+
public ngAfterViewInit() {
112+
// Remove after the first frame to re-enable transitions
113+
requestAnimationFrame(() => {
114+
this.element.nativeElement.style.removeProperty('--_ig-init-transition');
115+
});
116+
}
101117
}

projects/igniteui-angular/src/lib/directives/button/icon-button.directive.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, HostBinding, Input } from '@angular/core';
1+
import {Directive, ElementRef, HostBinding, Input} from '@angular/core';
22
import { IgxBaseButtonType, IgxButtonBaseDirective } from './button-base';
33

44
/**
@@ -78,4 +78,10 @@ export class IgxIconButtonDirective extends IgxButtonBaseDirective {
7878
public get outlined(): boolean {
7979
return this._type === IgxBaseButtonType.Outlined;
8080
}
81+
82+
constructor(
83+
public override element: ElementRef,
84+
) {
85+
super(element);
86+
}
8187
}

0 commit comments

Comments
 (0)