- { ! isTheme && product.icon && (
-
+ { ! isTheme && (
+ <>
+ { isLoading && (
+
+ ) }
+ { ! isLoading && product.icon && (
+
+ ) }
+ >
) }
@@ -60,10 +89,13 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
href={ product.url }
rel="noopener noreferrer"
>
- { product.title }
+ { isLoading ? ' ' : product.title }
- { productVendor && (
+ { isLoading && (
+
+ ) }
+ { ! isLoading && productVendor && (
{ __( 'By ', 'woocommerce' ) }
{ productVendor }
@@ -74,23 +106,27 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
{ ! isTheme && (
- { product.description }
+ { ! isLoading && product.description }
) }
-
- {
- // '0' is a free product
- product.price === 0
- ? __( 'Free download', 'woocommerce' )
- : currencySymbol + product.price
- }
-
-
- { product.price === 0
- ? ''
- : __( ' annually', 'woocommerce' ) }
-
+ { ! isLoading && (
+ <>
+
+ {
+ // '0' is a free product
+ product.price === 0
+ ? __( 'Free download', 'woocommerce' )
+ : currencySymbol + product.price
+ }
+
+
+ { product.price === 0
+ ? ''
+ : __( ' annually', 'woocommerce' ) }
+
+ >
+ ) }
diff --git a/plugins/woocommerce-admin/client/marketplace/components/product-list-content/no-results.tsx b/plugins/woocommerce-admin/client/marketplace/components/product-list-content/no-results.tsx
index b64d74125d3..cecd2b81f69 100644
--- a/plugins/woocommerce-admin/client/marketplace/components/product-list-content/no-results.tsx
+++ b/plugins/woocommerce-admin/client/marketplace/components/product-list-content/no-results.tsx
@@ -88,7 +88,11 @@ export default function NoResults( props: NoResultsProps ): JSX.Element {
function renderProductGroup() {
if ( isLoadingProductGroup ) {
- return
;
+ return (
+
+ );
}
if ( ! productGroup ) {
diff --git a/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.scss b/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.scss
index 16702332caa..c9a87f6503a 100644
--- a/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.scss
+++ b/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.scss
@@ -15,6 +15,13 @@
font-weight: 500;
margin-bottom: $medium-gap;
margin-top: $small-gap;
+
+ &.is-loading {
+ background: $skeleton-loader-color;
+ height: 26px;
+ margin: 0;
+ width: min(100%, 12em);
+ }
}
&__product-list-title--extensions,
@@ -36,4 +43,3 @@
text-decoration: none;
}
}
-
diff --git a/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.tsx b/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.tsx
index 83aaf5af862..0dd4843b852 100644
--- a/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.tsx
+++ b/plugins/woocommerce-admin/client/marketplace/components/product-list-header/product-list-header.tsx
@@ -3,6 +3,8 @@
*/
import { Link } from '@woocommerce/components';
import { __ } from '@wordpress/i18n';
+import classnames from 'classnames';
+
/**
* Internal dependencies
*/
@@ -10,15 +12,24 @@ import './product-list-header.scss';
interface ProductListHeaderProps {
title: string;
- groupURL: string;
+ groupURL: string | null;
}
export default function ProductListHeader(
props: ProductListHeaderProps
): JSX.Element {
const { title, groupURL } = props;
+ const isLoading = title === '';
+
+ const classNames = classnames(
+ 'woocommerce-marketplace__product-list-header',
+ {
+ 'is-loading': isLoading,
+ }
+ );
+
return (
-
+
{ title }
diff --git a/plugins/woocommerce-admin/client/marketplace/components/product-loader/product-loader.scss b/plugins/woocommerce-admin/client/marketplace/components/product-loader/product-loader.scss
deleted file mode 100644
index 560b46cf014..00000000000
--- a/plugins/woocommerce-admin/client/marketplace/components/product-loader/product-loader.scss
+++ /dev/null
@@ -1,72 +0,0 @@
-@import '../../stylesheets/_variables.scss';
-
-.woocommerce-marketplace {
- &__product-loader {
- margin-top: $grid-unit-20;
- }
-
- &__product-loader-cards {
- display: grid;
- background: linear-gradient(to right, $gray-0 40%, $gray-5 60%, $gray-0 80%);
- background-color: $gray-0;
- background-size: 500% 200%;
- animation: GradientSlide 4s linear infinite;
- height: 270px;
- }
-
- &__product-loader-divider {
- background: #fff;
- width: 24px;
- display: none;
- }
-
- .divider-1 {
- grid-column-start: 2;
- }
-}
-
-@media screen and (min-width: $breakpoint-medium) {
- .woocommerce-marketplace {
- &__product-loader-cards {
- grid-template-columns: repeat(2, 1fr);
- }
-
- .divider-1 {
- display: block;
- }
- }
-}
-
-@media screen and (min-width: $breakpoint-large) {
- .woocommerce-marketplace {
- &__product-loader-cards {
- grid-template-columns: repeat(3, 1fr);
- }
-
- .divider-2 {
- display: block;
- }
- }
-}
-
-@media screen and (min-width: $breakpoint-xlarge) {
- .woocommerce-marketplace {
- &__product-loader-cards {
- grid-template-columns: repeat(4, 1fr);
- }
-
- .divider-3 {
- display: block;
- }
- }
-}
-
-@keyframes GradientSlide {
- 0% {
- background-position: 100% 0;
- }
-
- 100% {
- background-position: -100% 0;
- }
-}
diff --git a/plugins/woocommerce-admin/client/marketplace/components/product-loader/product-loader.tsx b/plugins/woocommerce-admin/client/marketplace/components/product-loader/product-loader.tsx
index 293b1b6e4ba..d5103c6386d 100644
--- a/plugins/woocommerce-admin/client/marketplace/components/product-loader/product-loader.tsx
+++ b/plugins/woocommerce-admin/client/marketplace/components/product-loader/product-loader.tsx
@@ -5,15 +5,30 @@
/**
* Internal dependencies
*/
-import './product-loader.scss';
+import ProductListHeader from '../product-list-header/product-list-header';
+import ProductCard from '../product-card/product-card';
+
+interface ProductLoaderProps {
+ hasTitle?: boolean;
+ placeholderCount?: number;
+ type: string;
+}
+
+export default function ProductLoader(
+ props: ProductLoaderProps
+): JSX.Element {
+ const { hasTitle, type } = props;
+ const placeholderCount = props.placeholderCount || 12;
-export default function ProductLoader(): JSX.Element {
return (
-
-
-
-
-
+
+ { hasTitle !== false && (
+
+ ) }
+
+ { [ ...Array( placeholderCount ) ].map( ( element, i ) => (
+
+ ) ) }
);
diff --git a/plugins/woocommerce-admin/client/marketplace/components/products/products.tsx b/plugins/woocommerce-admin/client/marketplace/components/products/products.tsx
index dd712482ffc..af6f017cc91 100644
--- a/plugins/woocommerce-admin/client/marketplace/components/products/products.tsx
+++ b/plugins/woocommerce-admin/client/marketplace/components/products/products.tsx
@@ -88,7 +88,8 @@ export default function Products( props: ProductsProps ): JSX.Element {
const containerClassName = classnames( baseContainerClass + label );
const productListTitleClassName = classnames(
'woocommerce-marketplace__product-list-title',
- baseContainerClass + baseProductListTitleClass + label
+ baseContainerClass + baseProductListTitleClass + label,
+ { 'is-loading': isLoading }
);
const viewAllButonClassName = classnames(
'woocommerce-marketplace__view-all-button',
@@ -97,7 +98,14 @@ export default function Products( props: ProductsProps ): JSX.Element {
function content() {
if ( isLoading ) {
- return
;
+ return (
+ <>
+ { props.categorySelector && (
+
+ ) }
+
+ >
+ );
}
if ( products.length === 0 ) {
@@ -124,7 +132,9 @@ export default function Products( props: ProductsProps ): JSX.Element {
return (
-
{ title }
+
+ { isLoading ? ' ' : title }
+
{ content() }
);
diff --git a/plugins/woocommerce-admin/client/marketplace/stylesheets/_variables.scss b/plugins/woocommerce-admin/client/marketplace/stylesheets/_variables.scss
index 275941fd774..1ac3d139c5e 100644
--- a/plugins/woocommerce-admin/client/marketplace/stylesheets/_variables.scss
+++ b/plugins/woocommerce-admin/client/marketplace/stylesheets/_variables.scss
@@ -32,3 +32,4 @@ $woo-purple-50: #7f54b3;
$wp-gray-0: $gray-0;
$wp-gray-50: $gray-50;
$wp-gray-60: $gray-60;
+$skeleton-loader-color: #f0f0f0;
diff --git a/plugins/woocommerce/changelog/fix-wccom-18034-modern-skeleton-loaders b/plugins/woocommerce/changelog/fix-wccom-18034-modern-skeleton-loaders
new file mode 100644
index 00000000000..da6ff1e1a67
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-wccom-18034-modern-skeleton-loaders
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+Comment: Improved loading indicators on WooCommerce > Extensions so they more-accurately reflect the layout of the content that will replace them.
+