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

fix(Alert): improve open/close animation #769

Merged
merged 5 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions packages/beeq/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,8 @@ declare global {
interface HTMLBqAlertElementEventMap {
"bqHide": any;
"bqShow": any;
"bqAfterOpen": any;
"bqAfterClose": any;
}
interface HTMLBqAlertElement extends Components.BqAlert, HTMLStencilElement {
addEventListener<K extends keyof HTMLBqAlertElementEventMap>(type: K, listener: (this: HTMLBqAlertElement, ev: BqAlertCustomEvent<HTMLBqAlertElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
Expand Down Expand Up @@ -1979,11 +1981,19 @@ declare namespace LocalJSX {
*/
"hideIcon"?: boolean;
/**
* Callback handler to be called when the notification is hidden
* Callback handler to be called after the alert has been closed
*/
"onBqAfterClose"?: (event: BqAlertCustomEvent<any>) => void;
/**
* Callback handler to be called after the alert has been opened
*/
"onBqAfterOpen"?: (event: BqAlertCustomEvent<any>) => void;
/**
* Callback handler to be called when the alert is hidden
*/
"onBqHide"?: (event: BqAlertCustomEvent<any>) => void;
/**
* Callback handler to be called when the notification is shown
* Callback handler to be called when the alert is shown
*/
"onBqShow"?: (event: BqAlertCustomEvent<any>) => void;
/**
Expand Down
67 changes: 56 additions & 11 deletions packages/beeq/src/components/alert/bq-alert.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, Element, Event, EventEmitter, h, Host, Method, Prop, State, Watch } from '@stencil/core';
import { enter, leave } from 'el-transition';

import { ALERT_TYPE, TAlertType } from './bq-alert.types';
import { debounce, hasSlotContent, TDebounce, validatePropValue } from '../../shared/utils';
Expand Down Expand Up @@ -29,6 +30,7 @@ export class BqAlert {
private autoDismissDebounce: TDebounce<void>;
private bodyElem: HTMLDivElement;
private footerElem: HTMLDivElement;
private alertElement: HTMLDivElement;

// Reference to host HTML element
// ===================================
Expand Down Expand Up @@ -85,8 +87,16 @@ export class BqAlert {
handleOpenChange() {
this.autoDismissDebounce?.cancel();

if (!(this.autoDismiss && this.open)) return;
this.autoDismissDebounce();
if (!this.open) {
this.handleHide();
return;
}

this.handleShow();

if (this.autoDismiss) {
this.autoDismissDebounce();
}
}

@Watch('type')
Expand All @@ -98,11 +108,17 @@ export class BqAlert {
// Requires JSDocs for public API documentation
// ==============================================

/** Callback handler to be called when the notification is hidden */
@Event() bqHide: EventEmitter;
/** Callback handler to be called when the alert is hidden */
@Event() bqHide!: EventEmitter;

/** Callback handler to be called when the alert is shown */
@Event() bqShow!: EventEmitter;

/** Callback handler to be called when the notification is shown */
@Event() bqShow: EventEmitter;
/** Callback handler to be called after the alert has been opened */
@Event() bqAfterOpen!: EventEmitter;

/** Callback handler to be called after the alert has been closed */
@Event() bqAfterClose!: EventEmitter;

// Component lifecycle events
// Ordered by their natural call order
Expand All @@ -112,6 +128,13 @@ export class BqAlert {
this.checkPropValues();
this.handleTimeout();
}

componentDidLoad() {
if (!this.open) {
this.el.classList.add('is-hidden');
}
}

// Listeners
// ==============

Expand All @@ -125,33 +148,48 @@ export class BqAlert {
/** Method to be called to hide the alert component */
@Method()
async hide(): Promise<void> {
this.handleHide();
await this.handleHide();
}
/** Method to be called to show the alert component */
@Method()
async show(): Promise<void> {
this.handleShow();
await this.handleShow();
}

// Local methods
// Internal business logic.
// These methods cannot be called from the host element.
// =======================================================

private handleHide = () => {
private handleHide = async () => {
const ev = this.bqHide.emit(this.el);
if (!ev.defaultPrevented) {
await leave(this.alertElement);
this.el.classList.add('is-hidden');
this.handleTransitionEnd();
this.open = false;
}
};

private handleShow = () => {
private handleShow = async () => {
const ev = this.bqShow.emit(this.el);
if (!ev.defaultPrevented) {
this.open = true;
this.el.classList.remove('is-hidden');
await enter(this.alertElement);
this.handleTransitionEnd();
}
};

private handleTransitionEnd = () => {
if (this.open) {
this.bqAfterOpen.emit();
return;
}

this.bqAfterClose.emit();
};

private handleContentSlotChange = () => {
this.hasContent = hasSlotContent(this.bodyElem, 'body');
};
Expand Down Expand Up @@ -180,7 +218,7 @@ export class BqAlert {
render() {
return (
<Host
class={{ 'is-hidden': !this.open, 'is-sticky': this.sticky }}
class={{ 'is-sticky': this.sticky }}
aria-hidden={!this.open ? 'true' : 'false'}
hidden={!this.open ? 'true' : 'false'}
role="alert"
Expand All @@ -190,6 +228,13 @@ export class BqAlert {
[`bq-alert bq-alert__${this.type}`]: true,
'is-sticky': this.sticky,
}}
data-transition-enter="transition ease-out duration-300"
data-transition-enter-start="opacity-0"
data-transition-enter-end="opacity-100"
data-transition-leave="transition ease-in duration-200"
data-transition-leave-start="opacity-100"
data-transition-leave-end="opacity-0"
ref={(div) => (this.alertElement = div)}
part="wrapper"
>
{/* CLOSE BUTTON */}
Expand Down
3 changes: 1 addition & 2 deletions packages/beeq/src/components/alert/scss/bq-alert.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
}

.bq-alert {
@include animation-fade-in;
@apply relative flex min-w-[var(--bq-alert--min-width)] p-[var(--bq-alert--padding)];
@apply relative flex min-w-[var(--bq-alert--min-width)] p-[var(--bq-alert--padding)] transition-all;
@apply rounded-[var(--bq-alert--border-radius)] border-[length:--bq-alert--border-width];

border-style: var(--bq-alert--border-style);
Expand Down