Skip to content

Commit

Permalink
fix(sbb-notification): fix notification animation (#2274)
Browse files Browse the repository at this point in the history
  • Loading branch information
dauriamarco authored Jan 15, 2024
1 parent a64a3eb commit 5272043
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 18 deletions.
15 changes: 9 additions & 6 deletions src/components/notification/notification.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
--sbb-notification-timing-function: ease-in;
--sbb-notification-transition: max-height var(--sbb-notification-animation-duration)
var(--sbb-animation-duration-2x) var(--sbb-notification-timing-function),
margin var(--sbb-notification-animation-duration) var(--sbb-notification-timing-function),
padding var(--sbb-notification-animation-duration) var(--sbb-animation-duration-2x)
var(--sbb-notification-timing-function),
border var(--sbb-notification-animation-duration) var(--sbb-animation-duration-2x)
Expand All @@ -36,10 +37,6 @@
// As the notification has always a light background, we have to fix the focus outline color
// to default color for cases where the notification is used in a negative context.
--sbb-focus-outline-color: var(--sbb-focus-outline-color-default);

margin: 0;
transition: margin var(--sbb-notification-animation-duration)
var(--sbb-notification-timing-function);
}

:host(:is([data-state='opened'], [data-state='opening'])) {
Expand All @@ -50,12 +47,13 @@
);
--sbb-notification-transition: max-height var(--sbb-notification-animation-duration)
var(--sbb-notification-timing-function),
margin var(--sbb-notification-animation-duration) var(--sbb-notification-timing-function),
padding var(--sbb-notification-animation-duration) var(--sbb-notification-timing-function),
border var(--sbb-notification-animation-duration) var(--sbb-notification-timing-function),
visibility var(--sbb-notification-animation-duration) var(--sbb-notification-animation-duration)
var(--sbb-notification-timing-function),
opacity var(--sbb-notification-animation-duration) var(--sbb-notification-animation-duration)
var(--sbb-notification-timing-function);

margin: var(--sbb-notification-margin);
}

:host(:is([data-resize-disable-animation], [disable-animation])) {
Expand Down Expand Up @@ -88,6 +86,7 @@

.sbb-notification__wrapper {
position: relative;
margin: var(--sbb-notification-margin);
inset-inline-start: calc(
var(--sbb-notification-base-radius) - var(--sbb-notification-border-width)
);
Expand Down Expand Up @@ -208,11 +207,15 @@
visibility: hidden;
opacity: 0;
max-height: 0;
border-block: none;
margin: 0;
}

to {
visibility: visible;
opacity: 1;
max-height: var(--sbb-notification-max-height);
border-block: var(--sbb-notification-border);
margin: var(--sbb-notification-margin);
}
}
62 changes: 56 additions & 6 deletions src/components/notification/notification.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,28 @@ const trigger = (args: Args): TemplateResult => html`
</sbb-button>
`;

const simpleNotification = (
disabelAnimation: boolean,
type: string,
title: string,
): TemplateResult => html`
<sbb-notification
type="${type}"
title-content="${title}"
disable-animation
style="--sbb-notification-margin: 0 0 var(--sbb-spacing-fixed-4x) 0;"
${ref((notification?: Element) =>
(notification as SbbNotificationElement)?.addEventListener(
SbbNotificationElement.events.didOpen,
() => ((notification as SbbNotificationElement).disableAnimation = disabelAnimation),
{ once: true },
),
)}
>
This is a ${type} notification.
</sbb-notification>
`;

const pageContent = (): TemplateResult => html`
<p style="margin: 0;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
Expand All @@ -92,9 +114,28 @@ const pageContent = (): TemplateResult => html`

const DefaultTemplate = (args: Args): TemplateResult => html`
<sbb-notification
${sbbSpread(args)}
disable-animation
style="margin-block-end: var(--sbb-spacing-fixed-4x);"
${sbbSpread({ ...args, ['disable-animation']: true })}
style="--sbb-notification-margin: 0 0 var(--sbb-spacing-fixed-4x) 0;"
${ref((notification?: Element) =>
(notification as SbbNotificationElement)?.addEventListener(
SbbNotificationElement.events.didOpen,
() =>
((notification as SbbNotificationElement).disableAnimation = args['disable-animation']),
{ once: true },
),
)}
>
The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
dog.&nbsp;<sbb-link href="/" variant="block"> Link one</sbb-link>
<sbb-link href="/" variant="inline"> Link two</sbb-link>
<sbb-link href="/" variant="inline"> Link three</sbb-link>
</sbb-notification>
`;

const MultipleNotificationsTemplate = (args: Args): TemplateResult => html`
<sbb-notification
${sbbSpread({ ...args, ['disable-animation']: true })}
style="--sbb-notification-margin: 0 0 var(--sbb-spacing-fixed-4x) 0;"
${ref((notification?: Element) =>
(notification as SbbNotificationElement)?.addEventListener(
SbbNotificationElement.events.didOpen,
Expand All @@ -109,13 +150,16 @@ const DefaultTemplate = (args: Args): TemplateResult => html`
<sbb-link href="/" variant="inline"> Link two</sbb-link>
<sbb-link href="/" variant="inline"> Link three</sbb-link>
</sbb-notification>
${simpleNotification(args['disable-animation'], 'success', 'Success')}
${simpleNotification(args['disable-animation'], 'warn', 'Warn')}
${simpleNotification(args['disable-animation'], 'error', 'Error')}
`;

const SlottedTitleTemplate = (args: Args): TemplateResult => html`
<sbb-notification
${sbbSpread(args)}
disable-animation
style="margin-block-end: var(--sbb-spacing-fixed-4x);"
${sbbSpread({ ...args, ['disable-animation']: true })}
style="--sbb-notification-margin: 0 0 var(--sbb-spacing-fixed-4x) 0;"
${ref((notification?: Element) =>
(notification as SbbNotificationElement)?.addEventListener(
SbbNotificationElement.events.didOpen,
Expand Down Expand Up @@ -181,6 +225,12 @@ export const SlottedTitle: StoryObj = {
args: { ...basicArgs, 'title-content': undefined },
};

export const MultipleNotifications: StoryObj = {
render: MultipleNotificationsTemplate,
argTypes: basicArgTypes,
args: { ...basicArgs },
};

// We set the height of the div in Chromatic to avoid cropped snapshots
const meta: Meta = {
decorators: [
Expand Down
25 changes: 19 additions & 6 deletions src/components/notification/notification.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { CSSResultGroup, html, LitElement, nothing, TemplateResult } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { ref } from 'lit/directives/ref.js';

import { LanguageController } from '../core/common-behaviors';
import { setAttribute, toggleDatasetEntry } from '../core/dom';
Expand Down Expand Up @@ -82,7 +81,7 @@ export class SbbNotificationElement extends LitElement {
/**
* The state of the notification.
*/
@state() private _state: 'closed' | 'opening' | 'opened' | 'closing' = 'opened';
@state() private _state: 'closed' | 'opening' | 'opened' | 'closing' = 'closed';

private _notificationElement: HTMLElement;
private _resizeObserverTimeout: ReturnType<typeof setTimeout> | null = null;
Expand Down Expand Up @@ -115,9 +114,18 @@ export class SbbNotificationElement extends LitElement {
SbbNotificationElement.events.didClose,
);

private _open(): void {
if (this._state === 'closed') {
this._state = 'opening';
this._willOpen.emit();
this.disableAnimation && this._handleOpening();
}
}

public close(): void {
if (this._state === 'opened') {
this._state = 'closing';
this.style.setProperty('--sbb-notification-margin', '0');
this._willClose.emit();
this.disableAnimation && this._handleClosing();
}
Expand All @@ -134,9 +142,15 @@ export class SbbNotificationElement extends LitElement {
this._setInlineLinks();
}

protected override firstUpdated(): void {
this._willOpen.emit();
protected override async firstUpdated(): Promise<void> {
this._notificationElement = this.shadowRoot.querySelector(
'.sbb-notification__wrapper',
) as HTMLElement;
// We need to wait for the component's `updateComplete` in order to set the correct
// height to the notification element.
await this.updateComplete;
this._setNotificationHeight();
this._open();
}

public override disconnectedCallback(): void {
Expand Down Expand Up @@ -181,7 +195,7 @@ export class SbbNotificationElement extends LitElement {
}

private _onNotificationAnimationEnd(event: AnimationEvent): void {
if (this._state === 'opened' && event.animationName === 'open') {
if (this._state === 'opening' && event.animationName === 'open') {
this._handleOpening();
}
}
Expand Down Expand Up @@ -210,7 +224,6 @@ export class SbbNotificationElement extends LitElement {
class="sbb-notification__wrapper"
@transitionend=${(event: TransitionEvent) => this._onNotificationTransitionEnd(event)}
@animationend=${(event: AnimationEvent) => this._onNotificationAnimationEnd(event)}
${ref((el) => (this._notificationElement = el as HTMLElement))}
>
<div class="sbb-notification">
<sbb-icon
Expand Down

0 comments on commit 5272043

Please sign in to comment.