Add styling to marketplace to identify sponsored products (#45684)
* Pass 'Sponsored' detail down to product cards from API * Style a "Sponsored" label * Stripe on top of sponsored products * Add 'blob' next to sponsored listings * Fix indentation bug * Add changefile(s) from automation for the following project(s): woocommerce * Update plugins/woocommerce-admin/client/marketplace/components/product-card/product-card.tsx Co-authored-by: Remi Corson <remicorson@gmail.com> * Update plugins/woocommerce-admin/client/marketplace/components/product-card/product-card.tsx Co-authored-by: Remi Corson <remicorson@gmail.com> * Update plugins/woocommerce-admin/client/marketplace/components/product-card/product-card.tsx Co-authored-by: Remi Corson <remicorson@gmail.com> * Apply suggestions from code review Co-authored-by: Remi Corson <remicorson@gmail.com> * Add missing close parenthesis following linter changes * Make linter happier about hex colors (still needs variablising) * Fix margins around vendor name * Fixed height of product stripe * Linting * Moved color to variable and calculated alpha using Sass functions * Update plugins/woocommerce-admin/client/marketplace/components/product-card/product-card.scss * Update plugins/woocommerce-admin/client/marketplace/stylesheets/_variables.scss --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Remi Corson <remicorson@gmail.com>
This commit is contained in:
parent
99853c19bf
commit
b0ea77326f
|
@ -165,11 +165,22 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__vendor-details {
|
||||||
|
display: flex;
|
||||||
|
gap: $grid-unit-10;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&__separator {
|
||||||
|
color: $gray-300;
|
||||||
|
font-size: 28px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__vendor {
|
&__vendor {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: $grid-unit-05;
|
gap: $grid-unit-05;
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
/* Allow vendor link to "punch through" the "whole card clickable" trick: */
|
/* Allow vendor link to "punch through" the "whole card clickable" trick: */
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -181,6 +192,10 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__sponsored-label {
|
||||||
|
color: $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
&__description {
|
&__description {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
|
|
|
@ -24,6 +24,9 @@ export interface ProductCardProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProductCard( props: ProductCardProps ): JSX.Element {
|
function ProductCard( props: ProductCardProps ): JSX.Element {
|
||||||
|
const SPONSORED_PRODUCT_LABEL = 'promoted'; // what product.label indicates a sponsored placement
|
||||||
|
const SPONSORED_PRODUCT_STRIPE_SIZE = '5px'; // unfortunately can't be defined in CSS - height of "stripe"
|
||||||
|
|
||||||
const { isLoading, type } = props;
|
const { isLoading, type } = props;
|
||||||
const query = useQuery();
|
const query = useQuery();
|
||||||
// Get the product if provided; if not provided, render a skeleton loader
|
// Get the product if provided; if not provided, render a skeleton loader
|
||||||
|
@ -33,6 +36,8 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
|
||||||
vendorName: '',
|
vendorName: '',
|
||||||
vendorUrl: '',
|
vendorUrl: '',
|
||||||
icon: '',
|
icon: '',
|
||||||
|
label: null,
|
||||||
|
primary_color: null,
|
||||||
url: '',
|
url: '',
|
||||||
price: 0,
|
price: 0,
|
||||||
image: '',
|
image: '',
|
||||||
|
@ -40,6 +45,24 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
|
||||||
reviewsCount: null,
|
reviewsCount: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isSponsored(): boolean {
|
||||||
|
return SPONSORED_PRODUCT_LABEL === product.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sponsored products with a primary_color set have that color applied as a dynamically-colored stripe at the top of the card.
|
||||||
|
* In an ideal world this could be set in a data- attribute and we'd use CSS calc() and attr() to get it, but
|
||||||
|
* attr() doesn't have very good support yet, so we need to apply some inline CSS to stripe sponsored results.
|
||||||
|
*/
|
||||||
|
function inlineCss(): object {
|
||||||
|
if ( ! isSponsored() || ! product.primary_color ) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
background: `linear-gradient(${ product.primary_color } 0, ${ product.primary_color } ${ SPONSORED_PRODUCT_STRIPE_SIZE }, white ${ SPONSORED_PRODUCT_STRIPE_SIZE }, white)`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function recordTracksEvent( event: string, data: ExtraProperties ) {
|
function recordTracksEvent( event: string, data: ExtraProperties ) {
|
||||||
const tracksData = props.tracksData;
|
const tracksData = props.tracksData;
|
||||||
|
|
||||||
|
@ -104,11 +127,16 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
|
||||||
{
|
{
|
||||||
'is-loading': isLoading,
|
'is-loading': isLoading,
|
||||||
'is-small': props.small,
|
'is-small': props.small,
|
||||||
|
'is-sponsored': isSponsored(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className={ classNames } aria-hidden={ isLoading }>
|
<Card
|
||||||
|
className={ classNames }
|
||||||
|
aria-hidden={ isLoading }
|
||||||
|
style={ inlineCss() }
|
||||||
|
>
|
||||||
<div className="woocommerce-marketplace__product-card__content">
|
<div className="woocommerce-marketplace__product-card__content">
|
||||||
{ isTheme && (
|
{ isTheme && (
|
||||||
<div className="woocommerce-marketplace__product-card__image">
|
<div className="woocommerce-marketplace__product-card__image">
|
||||||
|
@ -158,12 +186,33 @@ function ProductCard( props: ProductCardProps ): JSX.Element {
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
{ isLoading && (
|
{ isLoading && (
|
||||||
<p className="woocommerce-marketplace__product-card__vendor" />
|
<p className="woocommerce-marketplace__product-card__vendor-details">
|
||||||
|
<span className="woocommerce-marketplace__product-card__vendor" />
|
||||||
|
</p>
|
||||||
) }
|
) }
|
||||||
{ ! isLoading && productVendor && (
|
{ ! isLoading && (
|
||||||
<p className="woocommerce-marketplace__product-card__vendor">
|
<p className="woocommerce-marketplace__product-card__vendor-details">
|
||||||
<span>{ __( 'By ', 'woocommerce' ) }</span>
|
{ productVendor && (
|
||||||
{ productVendor }
|
<span className="woocommerce-marketplace__product-card__vendor">
|
||||||
|
<span>
|
||||||
|
{ __( 'By ', 'woocommerce' ) }
|
||||||
|
</span>
|
||||||
|
{ productVendor }
|
||||||
|
</span>
|
||||||
|
) }
|
||||||
|
{ productVendor && isSponsored() && (
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className="woocommerce-marketplace__product-card__vendor-details__separator"
|
||||||
|
>
|
||||||
|
·
|
||||||
|
</span>
|
||||||
|
) }
|
||||||
|
{ isSponsored() && (
|
||||||
|
<span className="woocommerce-marketplace__product-card__sponsored-label">
|
||||||
|
{ __( 'Sponsored', 'woocommerce' ) }
|
||||||
|
</span>
|
||||||
|
) }
|
||||||
</p>
|
</p>
|
||||||
) }
|
) }
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -73,6 +73,8 @@ export default function ProductListContent( props: {
|
||||||
image: product.image,
|
image: product.image,
|
||||||
type: product.type,
|
type: product.type,
|
||||||
icon: product.icon,
|
icon: product.icon,
|
||||||
|
label: product.label,
|
||||||
|
primary_color: product.primary_color,
|
||||||
vendorName: product.vendorName,
|
vendorName: product.vendorName,
|
||||||
vendorUrl: product.vendorUrl
|
vendorUrl: product.vendorUrl
|
||||||
? appendURLParams( product.vendorUrl, [
|
? appendURLParams( product.vendorUrl, [
|
||||||
|
|
|
@ -39,6 +39,7 @@ export interface Product {
|
||||||
averageRating?: number | null;
|
averageRating?: number | null;
|
||||||
reviewsCount?: number | null;
|
reviewsCount?: number | null;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
primary_color?: string;
|
||||||
group?: string;
|
group?: string;
|
||||||
searchTerm?: string;
|
searchTerm?: string;
|
||||||
category?: string;
|
category?: string;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: enhancement
|
||||||
|
|
||||||
|
Made sponsored product listings in the Extensions marketplace easier to identify.
|
Loading…
Reference in New Issue