Skip to content

Commit 46259a7

Browse files
authored
refactor(toast,snackbar): Abstracted show/hide logic and code clean-ups (#1777)
1 parent e68a326 commit 46259a7

File tree

4 files changed

+39
-53
lines changed

4 files changed

+39
-53
lines changed

src/animations/player.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,5 @@ export function startViewTransition(
110110

111111
return { transition: document.startViewTransition(callback) };
112112
}
113+
114+
export type { AnimationController };

src/components/common/mixins/alert.ts

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
import { LitElement } from 'lit';
1+
import { LitElement, type PropertyValues } from 'lit';
22
import { property } from 'lit/decorators.js';
3-
4-
import type { addAnimationController } from '../../../animations/player.js';
3+
import type { AnimationController } from '../../../animations/player.js';
54
import { fadeIn, fadeOut } from '../../../animations/presets/fade/index.js';
65
import type { AbsolutePosition } from '../../types.js';
76
import { addInternalsController } from '../controllers/internals.js';
8-
import { watch } from '../decorators/watch.js';
97

108
// It'd be better to have this as a mixin rather than a base class once the analyzer
119
// knows how to resolve multiple mixin chains
1210

1311
export abstract class IgcBaseAlertLikeComponent extends LitElement {
14-
protected _autoHideTimeout?: number;
12+
declare protected abstract readonly _player: AnimationController;
1513

16-
declare protected abstract _animationPlayer: ReturnType<
17-
typeof addAnimationController
18-
>;
14+
protected _autoHideTimeout?: ReturnType<typeof setTimeout>;
1915

2016
/**
2117
* Whether the component is in shown state.
@@ -56,28 +52,33 @@ export abstract class IgcBaseAlertLikeComponent extends LitElement {
5652
});
5753
}
5854

59-
@watch('displayTime', { waitUntilFirstUpdate: true })
60-
protected displayTimeChange() {
61-
this.setAutoHideTimer();
62-
}
55+
protected override updated(props: PropertyValues<this>): void {
56+
if (props.has('displayTime')) {
57+
this._setAutoHideTimer();
58+
}
6359

64-
@watch('keepOpen', { waitUntilFirstUpdate: true })
65-
protected keepOpenChange() {
66-
clearTimeout(this._autoHideTimeout);
60+
if (props.has('keepOpen')) {
61+
clearTimeout(this._autoHideTimeout);
62+
}
6763
}
6864

69-
private async toggleAnimation(state: 'open' | 'close') {
70-
const animation = state === 'open' ? fadeIn : fadeOut;
71-
72-
const [_, event] = await Promise.all([
73-
this._animationPlayer.stopAll(),
74-
this._animationPlayer.play(animation()),
75-
]);
65+
private async _setOpenState(open: boolean): Promise<boolean> {
66+
let state: boolean;
67+
68+
if (open) {
69+
this.open = open;
70+
state = await this._player.playExclusive(fadeIn());
71+
this._setAutoHideTimer();
72+
} else {
73+
clearTimeout(this._autoHideTimeout);
74+
state = await this._player.playExclusive(fadeOut());
75+
this.open = open;
76+
}
7677

77-
return event.type === 'finish';
78+
return state;
7879
}
7980

80-
private setAutoHideTimer() {
81+
private _setAutoHideTimer(): void {
8182
clearTimeout(this._autoHideTimeout);
8283
if (this.open && this.displayTime > 0 && !this.keepOpen) {
8384
this._autoHideTimeout = setTimeout(() => this.hide(), this.displayTime);
@@ -86,26 +87,12 @@ export abstract class IgcBaseAlertLikeComponent extends LitElement {
8687

8788
/** Opens the component. */
8889
public async show(): Promise<boolean> {
89-
if (this.open) {
90-
return false;
91-
}
92-
93-
this.open = true;
94-
await this.toggleAnimation('open');
95-
this.setAutoHideTimer();
96-
return true;
90+
return this.open ? false : this._setOpenState(true);
9791
}
9892

9993
/** Closes the component. */
10094
public async hide(): Promise<boolean> {
101-
if (!this.open) {
102-
return false;
103-
}
104-
105-
clearTimeout(this._autoHideTimeout);
106-
await this.toggleAnimation('close');
107-
this.open = false;
108-
return true;
95+
return this.open ? this._setOpenState(false) : false;
10996
}
11097

11198
/** Toggles the open state of the component. */

src/components/snackbar/snackbar.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { html, nothing } from 'lit';
22
import { property } from 'lit/decorators.js';
3-
import { createRef, type Ref, ref } from 'lit/directives/ref.js';
4-
3+
import { createRef, ref } from 'lit/directives/ref.js';
54
import { addAnimationController } from '../../animations/player.js';
65
import { addThemingController } from '../../theming/theming-controller.js';
76
import IgcButtonComponent from '../button/button.js';
@@ -45,10 +44,11 @@ export default class IgcSnackbarComponent extends EventEmitterMixin<
4544
registerComponent(IgcSnackbarComponent, IgcButtonComponent);
4645
}
4746

48-
protected contentRef: Ref<HTMLElement> = createRef();
49-
protected override _animationPlayer: ReturnType<
50-
typeof addAnimationController
51-
> = addAnimationController(this, this.contentRef);
47+
protected readonly _contentRef = createRef<HTMLElement>();
48+
protected override readonly _player = addAnimationController(
49+
this,
50+
this._contentRef
51+
);
5252

5353
/**
5454
* The snackbar action button.
@@ -62,18 +62,18 @@ export default class IgcSnackbarComponent extends EventEmitterMixin<
6262
addThemingController(this, all);
6363
}
6464

65-
private handleClick() {
65+
private _handleClick(): void {
6666
this.emitEvent('igcAction');
6767
}
6868

6969
protected override render() {
7070
return html`
71-
<div ${ref(this.contentRef)} part="base" .inert=${!this.open}>
71+
<div ${ref(this._contentRef)} part="base" .inert=${!this.open}>
7272
<span part="message">
7373
<slot></slot>
7474
</span>
7575
76-
<slot name="action" part="action-container" @click=${this.handleClick}>
76+
<slot name="action" part="action-container" @click=${this._handleClick}>
7777
${this.actionText
7878
? html`<igc-button type="button" part="action" variant="flat">
7979
${this.actionText}

src/components/toast/toast.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { html } from 'lit';
2-
32
import { addAnimationController } from '../../animations/player.js';
43
import { addThemingController } from '../../theming/theming-controller.js';
54
import { registerComponent } from '../common/definitions/register.js';
@@ -19,9 +18,7 @@ export default class IgcToastComponent extends IgcBaseAlertLikeComponent {
1918
public static readonly tagName = 'igc-toast';
2019
public static override styles = [styles, shared];
2120

22-
protected override _animationPlayer: ReturnType<
23-
typeof addAnimationController
24-
> = addAnimationController(this);
21+
protected override readonly _player = addAnimationController(this);
2522

2623
/* blazorSuppress */
2724
public static register(): void {

0 commit comments

Comments
 (0)