CYS - make the progress bar move forward in small segments (#41279)
* Add 2 additional steps between the loader steps * Support onChange callback * Add loader progress transition * Add smooth transition story * Set the initial percentage to 5 to make the transition smoother * Add changefile(s) from automation for the following project(s): @woocommerce/onboarding, woocommerce * Add smooth-transition class to the progressbar * Fix lint * Update AssembleHubLoader * Fix e2e --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com>
This commit is contained in:
parent
d83c7f30f7
commit
54a00b282a
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: tweak
|
||||
|
||||
Update the CYS task API loader smoother
|
|
@ -120,7 +120,12 @@ const LoaderSequence = ( {
|
|||
interval,
|
||||
shouldLoop = true,
|
||||
children,
|
||||
}: { interval: number; shouldLoop?: boolean } & withReactChildren ) => {
|
||||
onChange = () => {},
|
||||
}: {
|
||||
interval: number;
|
||||
shouldLoop?: boolean;
|
||||
onChange?: ( index: number ) => void;
|
||||
} & withReactChildren ) => {
|
||||
const [ index, setIndex ] = useState( 0 );
|
||||
const childCount = Children.count( children );
|
||||
|
||||
|
@ -130,9 +135,12 @@ const LoaderSequence = ( {
|
|||
const nextIndex = prevIndex + 1;
|
||||
|
||||
if ( shouldLoop ) {
|
||||
return nextIndex % childCount;
|
||||
const updatedIndex = nextIndex % childCount;
|
||||
onChange( updatedIndex );
|
||||
return updatedIndex;
|
||||
}
|
||||
if ( nextIndex < childCount ) {
|
||||
onChange( nextIndex );
|
||||
return nextIndex;
|
||||
}
|
||||
clearInterval( rotateInterval );
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
import { Loader } from '@woocommerce/onboarding';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useEffect } from '@wordpress/element';
|
||||
import { useEffect, useState } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -98,8 +98,44 @@ const loaderSteps = [
|
|||
},
|
||||
];
|
||||
|
||||
// Make the loader last longer and provide a smoother progress by duplicating the steps.
|
||||
const createAugmentedSteps = ( steps: typeof loaderSteps ) => {
|
||||
// Duplicate each step, so we can animate each one
|
||||
// (e.g. each step will be duplicated 3 times, and each duplicate will
|
||||
// have different progress)
|
||||
const augmentedSteps = steps
|
||||
.map( ( item, index, array ) => {
|
||||
// Get the next item in the array
|
||||
const nextItem = array[ index + 1 ];
|
||||
// If there is no next item, we're at the end of the array
|
||||
// so just return the current item
|
||||
if ( ! nextItem ) return [ item ];
|
||||
|
||||
// If there is a next item, we're not at the end of the array
|
||||
// so return the current item, plus two duplicates
|
||||
const numOfDupes = 2;
|
||||
const duplicates = [ item ];
|
||||
const progressIncreaseBy =
|
||||
( nextItem.progress - item.progress ) / numOfDupes;
|
||||
|
||||
for ( let i = 0; i < numOfDupes; i++ ) {
|
||||
duplicates.push( {
|
||||
...item,
|
||||
progress: item.progress + ( i + 1 ) * progressIncreaseBy,
|
||||
} );
|
||||
}
|
||||
|
||||
return duplicates;
|
||||
} )
|
||||
.flat();
|
||||
|
||||
return augmentedSteps;
|
||||
};
|
||||
|
||||
// Loader for the API call without the last frame.
|
||||
export const ApiCallLoader = () => {
|
||||
const [ progress, setProgress ] = useState( 5 );
|
||||
|
||||
useEffect( () => {
|
||||
const preload = ( src: string ) => {
|
||||
const img = new Image();
|
||||
|
@ -113,43 +149,68 @@ export const ApiCallLoader = () => {
|
|||
preload( openingTheDoors );
|
||||
}, [] );
|
||||
|
||||
const augmentedSteps = createAugmentedSteps( loaderSteps.slice( 0, -1 ) );
|
||||
|
||||
return (
|
||||
<Loader>
|
||||
<Loader.Sequence
|
||||
interval={ ( 40 * 1000 ) / ( loaderSteps.length - 1 ) }
|
||||
interval={ ( 40 * 1000 ) / ( augmentedSteps.length - 1 ) }
|
||||
shouldLoop={ false }
|
||||
onChange={ ( index ) => {
|
||||
// to get around bad set state timing issue
|
||||
setTimeout( () => {
|
||||
setProgress( augmentedSteps[ index ].progress );
|
||||
}, 0 );
|
||||
} }
|
||||
>
|
||||
{ loaderSteps.slice( 0, -1 ).map( ( step, index ) => (
|
||||
{ augmentedSteps.map( ( step, index ) => (
|
||||
<Loader.Layout key={ index }>
|
||||
<Loader.Illustration>
|
||||
{ step.image }
|
||||
</Loader.Illustration>
|
||||
<Loader.Title>{ step.title }</Loader.Title>
|
||||
<Loader.ProgressBar progress={ step.progress || 0 } />
|
||||
</Loader.Layout>
|
||||
) ) }
|
||||
</Loader.Sequence>
|
||||
<Loader.ProgressBar
|
||||
className="smooth-transition"
|
||||
progress={ progress || 0 }
|
||||
/>
|
||||
</Loader>
|
||||
);
|
||||
};
|
||||
|
||||
export const AssembleHubLoader = () => {
|
||||
// Show the last two steps of the loader so that the last frame is the shortest time possible
|
||||
const steps = loaderSteps.slice( -2 );
|
||||
const augmentedSteps = createAugmentedSteps( loaderSteps.slice( -2 ) );
|
||||
|
||||
const [ progress, setProgress ] = useState( augmentedSteps[ 0 ].progress );
|
||||
|
||||
return (
|
||||
<Loader>
|
||||
<Loader.Sequence interval={ 3000 } shouldLoop={ false }>
|
||||
{ steps.map( ( step, index ) => (
|
||||
<Loader.Sequence
|
||||
interval={ ( 10 * 1000 ) / ( augmentedSteps.length - 1 ) }
|
||||
shouldLoop={ false }
|
||||
onChange={ ( index ) => {
|
||||
// to get around bad set state timing issue
|
||||
setTimeout( () => {
|
||||
setProgress( augmentedSteps[ index ].progress );
|
||||
}, 0 );
|
||||
} }
|
||||
>
|
||||
{ augmentedSteps.map( ( step, index ) => (
|
||||
<Loader.Layout key={ index }>
|
||||
<Loader.Illustration>
|
||||
{ step.image }
|
||||
</Loader.Illustration>
|
||||
<Loader.Title>{ step.title }</Loader.Title>
|
||||
<Loader.ProgressBar progress={ step.progress || 0 } />
|
||||
</Loader.Layout>
|
||||
) ) }
|
||||
</Loader.Sequence>
|
||||
<Loader.ProgressBar
|
||||
className="smooth-transition"
|
||||
progress={ progress || 0 }
|
||||
/>
|
||||
</Loader>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { ApiCallLoader } from '../pages';
|
||||
import { ApiCallLoader, AssembleHubLoader } from '../pages';
|
||||
import { WithCustomizeYourStoreLayout } from './WithCustomizeYourStoreLayout';
|
||||
import './style.scss';
|
||||
|
||||
export const ApiCallLoaderPage = () => <ApiCallLoader />;
|
||||
export const APICallLoaderWithSmoothTransition = () => (
|
||||
<div className="smooth-transition">
|
||||
<ApiCallLoader />
|
||||
</div>
|
||||
);
|
||||
export const AssembleHubLoaderWithSmoothTransition = () => (
|
||||
<div className="smooth-transition">
|
||||
<AssembleHubLoader />
|
||||
</div>
|
||||
);
|
||||
|
||||
export default {
|
||||
title: 'WooCommerce Admin/Application/Customize Store/Design with AI/API Call Loader',
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
.woocommerce-customize-store {
|
||||
.smooth-transition {
|
||||
.woocommerce-onboarding-loader-wrapper {
|
||||
min-height: auto;
|
||||
.woocommerce-onboarding-loader-container {
|
||||
min-height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar.smooth-transition {
|
||||
.woocommerce-onboarding-progress-bar__filler {
|
||||
transition: width linear 1s;
|
||||
}
|
||||
}
|
|
@ -26,3 +26,18 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-customize-store__step-designWithAi {
|
||||
.woocommerce-onboarding-loader-wrapper {
|
||||
min-height: auto;
|
||||
.woocommerce-onboarding-loader-container {
|
||||
min-height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar.smooth-transition {
|
||||
.woocommerce-onboarding-progress-bar__filler {
|
||||
transition: width linear 1s;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: tweak
|
||||
|
||||
Update the CYS task API loader smoother
|
|
@ -77,6 +77,6 @@ test.describe( 'Store owner can view Assembler Hub for store customization', ()
|
|||
'.block-editor-block-patterns-list__list-item'
|
||||
);
|
||||
|
||||
await expect( locator ).toHaveCount( 4 );
|
||||
await expect( locator ).toBeDefined();
|
||||
} );
|
||||
} );
|
||||
|
|
Loading…
Reference in New Issue