Skip to content

Commit

Permalink
Enhance toast progress component (#31)
Browse files Browse the repository at this point in the history
* Enhance toast progress component

* Updated toast styles

* remove unused params

* Updated animation

* update changelog

* Removed leftover console.log

---------

Co-authored-by: Miro Mărgineanu <[email protected]>
  • Loading branch information
DanutIlie and MiroMargineanu authored Feb 5, 2025
1 parent cbe4853 commit be899d1
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 40 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- [Enhance toast progress component](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/31)
- [Added transactions table styling](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/30)
- [Added react output config](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/29)
- [Added Trim and CopyButton components](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/28)
Expand Down
8 changes: 4 additions & 4 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ export namespace Components {
"transactionClass"?: string;
}
interface TransactionToastProgress {
"currentRemaining"?: number;
"progressClass": string;
"endTime"?: number;
"startTime"?: number;
}
interface TransactionToastWrapper {
"wrapperClass": string;
Expand Down Expand Up @@ -669,8 +669,8 @@ declare namespace LocalJSX {
"transactionClass"?: string;
}
interface TransactionToastProgress {
"currentRemaining"?: number;
"progressClass"?: string;
"endTime"?: number;
"startTime"?: number;
}
interface TransactionToastWrapper {
"wrapperClass"?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

## Properties

| Property | Attribute | Description | Type | Default |
| ------------------ | ------------------- | ----------- | -------- | ------------------------------ |
| `currentRemaining` | `current-remaining` | | `number` | `undefined` |
| `progressClass` | `progress-class` | | `string` | `'transaction-toast-progress'` |
| Property | Attribute | Description | Type | Default |
| ----------- | ------------ | ----------- | -------- | ----------- |
| `endTime` | `end-time` | | `number` | `undefined` |
| `startTime` | `start-time` | | `number` | `undefined` |


## Dependencies
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,108 @@
@keyframes progressiveFixedWidthExpansion {
from {
width: min(var(--start-width, 0%), 80%);
}

to {
width: 80%;
}
}

@keyframes progressiveInfiniteWidthExpansion {
from {
width: min(var(--start-width, 0%), 100%);
}

to {
width: 100%;
}
}

@keyframes quickWidthExpansion {
from {
width: 0%;
}

to {
width: 100%;
}
}

.transaction-toast-progress {
position: relative;
}

.transaction-toast-bar {
.transaction-toast-bar-wrapper {
transition: opacity 250ms ease-in;
background-color: lightgray;
position: absolute;
pointer-events: none;
left: -0.5rem;
right: -0.5rem;
bottom: -0.5rem;
top: -0.5rem;
background-color: gray;
opacity: 0.25;
transition: width 0.6s ease;
max-width: calc(100% + 1rem);
left: 0;
top: 0;
opacity: 25%;
bottom: 0;
right: 0;
display: flex;
overflow: hidden;
border-radius: 0.25rem;
flex-direction: row-reverse;
}

.transaction-toast-bar {
height: 100%;
right: 0;
top: 0;
bottom: 0;
}

.transaction-toast-bar.fixed {
width: min(var(--start-width, 0%), 50%);
background-color: white;
animation-name: progressiveFixedWidthExpansion;
animation-duration: var(--animation-duration, 6s);
animation-timing-function: cubic-bezier(0.5, 0.95, 0, 0.35);
animation-fill-mode: forwards;
}

.transaction-toast-bar.infinite {
width: 20%;
display: flex;
flex-direction: row-reverse;
}

.transaction-toast-bar.infinite .transaction-toast-bar-line {
width: 0%;
background-color: white;
animation-name: progressiveInfiniteWidthExpansion;
animation-duration: var(--animation-duration, 60s);
animation-timing-function: cubic-bezier(0.1, 0.95, 0.25, 0.75);
animation-fill-mode: forwards;
animation-delay: var(--animation-delay, 6s);
height: 100%;
position: relative;
}

.transaction-toast-bar.infinite .transaction-toast-bar-line:before {
position: absolute;
background-color: white;
content: '';
width: calc(4px / 2);
right: -1px;
top: 0;
bottom: 0;
}

.transaction-toast-bar.fill {
width: 0%;
position: absolute;
background-color: white;
}

.transaction-toast-bar.fill.animate {
animation: quickWidthExpansion 250ms linear forwards;
}

.transaction-toast-bar-content {
z-index: 1;
position: relative;
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,97 @@
import { Component, h,Prop } from '@stencil/core';
import { Component, Fragment, Prop, State, Watch, h } from '@stencil/core';
import classNames from 'classnames';

const DEFAULT_INFINITE_ANIMATION_DURATION = 30;

@Component({
tag: 'transaction-toast-progress',
styleUrl: 'transaction-toast-progress.css',
shadow: true,
})
export class ToastProgress {
@Prop() progressClass: string = 'transaction-toast-progress';
@Prop() currentRemaining?: number;
private timeElapsedTimeoutReference?: ReturnType<typeof setTimeout>;

render() {
if (!this.currentRemaining) {
return <slot></slot>;
@Prop() startTime?: number;
@Prop() endTime?: number;

@State() currentTimestamp: number = Date.now() / 1000;
@State() hasTimeElapsed: boolean = false;
@State() expectedTransactionDuration: number = 0;
@State() secondsPassedSinceStart: number = 0;
@State() shouldShowProgressBar: boolean = false;
@State() percentagePassedSinceStart: number = 0;
@State() shouldQuickFill: boolean = false;
@State() infiniteProgressDelay: number = 0;
@State() infinitePercentagePassedSinceStart: number = 0;
@State() infinitePercentageAnimationDuration: number = DEFAULT_INFINITE_ANIMATION_DURATION + (this.endTime - this.startTime) * 2;

componentWillLoad() {
this.updateProgress();
}

@Watch('startTime')
@Watch('endTime')
handleTimeChange() {
this.updateProgress();
}

private updateProgress() {
this.shouldShowProgressBar = Boolean(this.endTime) && Boolean(this.startTime);

if (!this.shouldShowProgressBar) {
this.shouldQuickFill = true;
this.timeElapsedTimeoutReference = setTimeout(() => (this.hasTimeElapsed = true), 500);
return;
}

this.currentTimestamp = Date.now() / 1000;
this.expectedTransactionDuration = this.endTime - this.startTime;
this.secondsPassedSinceStart = this.currentTimestamp - this.startTime;
this.percentagePassedSinceStart = this.expectedTransactionDuration > 0 ? (this.secondsPassedSinceStart / this.expectedTransactionDuration) * 100 : 0;
this.infiniteProgressDelay = Math.max(0, this.expectedTransactionDuration - this.secondsPassedSinceStart);
this.infinitePercentagePassedSinceStart = (this.secondsPassedSinceStart / (this.expectedTransactionDuration + this.infinitePercentageAnimationDuration)) * 100;
}

disconnectedCallback() {
if (this.timeElapsedTimeoutReference) {
clearTimeout(this.timeElapsedTimeoutReference);
}
}

render() {
return (
<div class={this.progressClass}>
<div
class="transaction-toast-bar"
style={{ width: `${this.currentRemaining}%` }}
role="progressbar"
aria-valuemin={0}
aria-valuemax={100}
aria-valnow={this.currentRemaining}
/>
<slot></slot>
</div>
<Fragment>
<div class="transaction-toast-bar-wrapper" style={{ opacity: this.hasTimeElapsed ? '0' : '1' }}>
<div
class="transaction-toast-bar fixed"
style={{
'--animation-duration': `${this.expectedTransactionDuration}s`,
'--start-width': `${this.percentagePassedSinceStart}%`,
}}
/>

<div class="transaction-toast-bar infinite">
<div
class="transaction-toast-bar-line"
style={{
'--start-width': `${this.infinitePercentagePassedSinceStart}%`,
'--animation-duration': `${this.infinitePercentageAnimationDuration}s`,
'--animation-delay': `${this.infiniteProgressDelay}s`,
}}
/>
</div>

<div
class={classNames('transaction-toast-bar fill', {
animate: this.shouldQuickFill,
})}
/>
</div>

<div class="transaction-toast-bar-content">
<slot />
</div>
</Fragment>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ export class TransactionToast {
render() {
return (
<transaction-toast-wrapper wrapperId={`toast-${this.toastId}`} wrapperClass={this.wrapperClass}>
<transaction-toast-progress
key={this.toastId}
progressClass={this.transactionProgressState?.progressClass}
currentRemaining={this.transactionProgressState?.currentRemaining}
>
<transaction-toast-progress key={this.toastId} startTime={this.transactionProgressState?.startTime} endTime={this.transactionProgressState?.endTime}>
<transaction-toast-content
onDeleteToast={() => this.handleDeleteToast.emit(this.toastId)}
processedTransactionsStatus={this.processedTransactionsStatus}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export interface IToastDataState {

export interface ITransactionProgressState {
progressClass?: string;
currentRemaining: number;
startTime: number;
endTime: number;
isCrossShard: boolean;
}

export interface ITransaction {
Expand Down

0 comments on commit be899d1

Please sign in to comment.