Marketplace design improvements (#41505)

* Not connected screen fixes

* Table improvements

* Success notice icon

* Use the same layout of columns for both tables

* Popover

* Add changefile(s) from automation for the following project(s): woocommerce

* CSS lint fixes

* Styling tweaks. Changed font-weight of `.woocommerce-marketplace__product-list-title` to 400, to correspond with the correct weight of the titles like "Installed on this store" in the My Subscriptions section.

* Undo refresh move

* Fix subgrid max widths

* Fic status height

* Update collaborate link

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: And Finally <andfinally@users.noreply.github.com>
This commit is contained in:
berislav grgičak 2023-11-21 08:08:26 +01:00 committed by GitHub
parent 5fe2e401f0
commit 48d7490c2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 216 additions and 72 deletions

View File

@ -8,3 +8,6 @@ export const MARKETPLACE_CATEGORY_API_PATH =
export const MARKETPLACE_ITEMS_PER_PAGE = 60;
export const MARKETPLACE_SEARCH_RESULTS_PER_PAGE = 8;
export const MARKETPLACE_CART_PATH = MARKETPLACE_HOST + '/cart/';
export const MARKETPLACE_COLLABORATION_PATH =
MARKETPLACE_HOST +
'/document/managing-woocommerce-com-subscriptions/#transfer-a-woocommerce-com-subscription';

View File

@ -5,6 +5,7 @@
margin: auto;
max-width: $content-max-width;
padding: $grid-unit-30 $grid-unit-20;
min-height: 500px;
}
@media screen and (min-width: $breakpoint-medium) {

View File

@ -1,4 +1,5 @@
@import '@wordpress/base-styles/_colors.native.scss';
@import '../../stylesheets/_variables.scss';
.woocommerce-marketplace__my-subscriptions__header {
display: flex;
@ -48,7 +49,7 @@
.woocommerce-marketplace__my-subscriptions__table-description {
font-size: 13px;
margin-top: $grid-unit-05;
margin: 1em 0;
line-height: 20px;
color: $gray-700;
@ -60,6 +61,9 @@
svg {
fill: #007cba;
margin-left: 2px;
width: 16px;
height: 16px;
}
}
@ -71,6 +75,8 @@
}
.woocommerce-marketplace__my-subscriptions__product {
$product-icon-size: 40px;
display: flex;
align-items: center;
color: $gray-900;
@ -83,14 +89,20 @@
&-icon img {
border-radius: 4px;
width: 40px;
width: $product-icon-size;
}
&-icon svg {
border-radius: 4px;
padding: $grid-unit-10;
fill: $gray-600;
background-color: $gray-200;
&-icon {
width: $product-icon-size;
height: $product-icon-size;
svg {
border-radius: 4px;
padding: $grid-unit-10;
fill: $gray-600;
background-color: $gray-200;
width: $product-icon-size;
height: $product-icon-size;
}
}
}
@ -103,7 +115,7 @@
align-items: center;
border-radius: 2px;
border: none;
padding: 2px 8px;
padding: 2px $grid-unit-10;
margin-left: $grid-unit-15;
text-align: left;
white-space: nowrap;
@ -129,12 +141,18 @@
}
}
.woocommerce-marketplace__my-subscriptions__popover .components-popover__content {
border: 1px solid $gray-400;
width: 300px;
border-radius: 2px;
padding: $grid-unit-15;
color: $gray-900;
.woocommerce-marketplace__my-subscriptions__popover {
top: -8px !important;
.components-popover__content {
border: none;
width: 300px;
border-radius: 2px;
padding: $grid-unit-15;
color: $gray-900;
a {
text-decoration: none;
}
}
}
.components-base-control.woocommerce-marketplace__my-subscriptions__activation {
@ -149,12 +167,26 @@
padding: 0 12px;
}
.woocommerce-marketplace__my-subscriptions .woocommerce-table.is-empty {
background: none;
border: 1px solid var(--gutenberg-gray-100, #f0f0f0);
flex-direction: column;
gap: $grid-unit-15;
margin-top: $grid-unit-30;
.woocommerce-marketplace__my-subscriptions {
.woocommerce-table__empty-item,
.woocommerce-table__header,
.woocommerce-table__item {
padding: $grid-unit-10 $grid-unit-30;
align-items: center;
display: flex;
}
.woocommerce-table__table tr:hover {
background: #f8f9fa;
}
.woocommerce-table.is-empty {
background: none;
border: 1px solid var(--gutenberg-gray-100, #f0f0f0);
flex-direction: column;
gap: $grid-unit-15;
margin-top: $grid-unit-30;
}
}
.woocommerce-marketplace__my-subscriptions .components-button.is-link {
@ -182,21 +214,23 @@
.woocommerce-marketplace__my-subscriptions__header {
margin-top: $grid-unit-20;
margin-bottom: $grid-unit-10;
font-size: 20px;
font-size: $default-font-size;
}
.woocommerce-marketplace__my-subscriptions__description {
text-align: center;
font-size: 13px;
font-size: $default-font-size;
line-height: 20px;
font-weight: 400;
color: var(--gutenberg-gray-700);
margin-top: 0;
margin-bottom: $grid-unit-30;
}
}
.woocommerce-marketplace__my-subscriptions__table__header--actions {
text-align: right;
justify-content: flex-end;
}
.woocommerce-marketplace__my-subscriptions__actions {
@ -258,3 +292,34 @@
padding: 0;
}
}
.woocommerce-marketplace__my-subscriptions {
display: grid;
grid-template-columns: repeat(5, auto);
.woocommerce-marketplace__my-subscriptions-section {
margin: 1em 0;
> * {
grid-column: span 5;
}
}
.woocommerce-table__table,
.woocommerce-marketplace__my-subscriptions-section {
&,
& table,
& tbody,
& thead,
& tr {
grid-column: span 5;
display: grid;
grid-template-columns: subgrid;
max-width: calc(100vw - (2 * #{$grid-unit-20}));
@media screen and (min-width: 783px) {
max-width: calc(100vw - (2 * #{$grid-unit-40}) - $admin-menu-width-collapsed);
}
@media screen and (min-width: 960px) {
max-width: calc(100vw - (2 * #{$grid-unit-40}) - $admin-menu-width);
}
}
}
}

View File

@ -80,17 +80,17 @@ export default function MySubscriptions(): JSX.Element {
<section className="woocommerce-marketplace__my-subscriptions__notices">
<Notices />
</section>
<section className="woocommerce-marketplace__my-subscriptions__installed">
<section className="woocommerce-marketplace__my-subscriptions-section woocommerce-marketplace__my-subscriptions__installed">
<header className="woocommerce-marketplace__my-subscriptions__header">
<div>
<h2 className="woocommerce-marketplace__my-subscriptions__heading">
{ __( 'Installed on this store', 'woocommerce' ) }
</h2>
<span className="woocommerce-marketplace__my-subscriptions__table-description">
<p className="woocommerce-marketplace__my-subscriptions__table-description">
{ installedTableDescription }
</span>
</p>
</div>
<div>
<div className="woocommerce-marketplace__my-subscriptions__header-refresh">
<RefreshButton />
</div>
</header>
@ -102,7 +102,7 @@ export default function MySubscriptions(): JSX.Element {
/>
</section>
<section className="woocommerce-marketplace__my-subscriptions__available">
<section className="woocommerce-marketplace__my-subscriptions-section woocommerce-marketplace__my-subscriptions__available">
<h2 className="woocommerce-marketplace__my-subscriptions__heading">
{ __( 'Available to use', 'woocommerce' ) }
</h2>

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { Button, Icon } from '@wordpress/components';
import { Button } from '@wordpress/components';
import { useContext, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
@ -40,10 +40,7 @@ export default function ConnectButton( props: ConnectProps ) {
__( '%s successfully connected.', 'woocommerce' ),
props.subscription.product_name
),
NoticeStatus.Success,
{
icon: <Icon icon="yes" />,
}
NoticeStatus.Success
);
setIsConnecting( false );
if ( props.onClose ) {

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { Button, Icon } from '@wordpress/components';
import { Button } from '@wordpress/components';
import { dispatch, useSelect } from '@wordpress/data';
import { useContext } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
@ -59,10 +59,7 @@ export default function Install( props: InstallProps ) {
__( '%s successfully installed.', 'woocommerce' ),
props.subscription.product_name
),
NoticeStatus.Success,
{
icon: <Icon icon="yes" />,
}
NoticeStatus.Success
);
stopInstall();
} );

View File

@ -7,8 +7,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { MARKETPLACE_CART_PATH } from '../../../constants';
import { appendURLParams } from '../../../../utils/functions';
import { renewUrl } from '../../../../utils/functions';
import { Subscription } from '../../types';
interface RenewProps {
@ -17,14 +16,11 @@ interface RenewProps {
}
export default function RenewButton( props: RenewProps ) {
const renewUrl = appendURLParams( MARKETPLACE_CART_PATH, [
[ 'renew_product', props.subscription.product_id.toString() ],
[ 'product_key', props.subscription.product_key ],
[ 'order_id', props.subscription.order_id.toString() ],
] );
return (
<Button href={ renewUrl } variant={ props.variant ?? 'secondary' }>
<Button
href={ renewUrl( props.subscription ) }
variant={ props.variant ?? 'secondary' }
>
{ __( 'Renew', 'woocommerce' ) }
</Button>
);

View File

@ -7,8 +7,7 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { MARKETPLACE_CART_PATH } from '../../../constants';
import { appendURLParams } from '../../../../utils/functions';
import { subscribeUrl } from '../../../../utils/functions';
import { Subscription } from '../../types';
interface SubscribeProps {
@ -17,11 +16,11 @@ interface SubscribeProps {
}
export default function SubscribeButton( props: SubscribeProps ) {
const subscribeUrl = appendURLParams( MARKETPLACE_CART_PATH, [
[ 'add-to-cart', props.subscription.product_id.toString() ],
] );
return (
<Button href={ subscribeUrl } variant={ props.variant ?? 'secondary' }>
<Button
href={ subscribeUrl( props.subscription ) }
variant={ props.variant ?? 'secondary' }
>
{ __( 'Subscribe', 'woocommerce' ) }
</Button>
);

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { Button, Icon } from '@wordpress/components';
import { Button } from '@wordpress/components';
import { useContext, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
@ -79,10 +79,7 @@ export default function Update( props: UpdateProps ) {
__( '%s updated successfully.', 'woocommerce' ),
props.subscription.product_name
),
NoticeStatus.Success,
{
icon: <Icon icon="yes" />,
}
NoticeStatus.Success
);
setIsUpdating( false );
} );

View File

@ -47,10 +47,7 @@ export default function ActionsDropdownMenu( props: {
return (
<DropdownMenu
icon={ moreVertical }
label={ __(
'See more things you can do with this subscription',
'woocommerce'
) }
label={ __( 'Actions', 'woocommerce' ) }
controls={ controls }
/>
);

View File

@ -5,6 +5,7 @@ import { TableRow } from '@woocommerce/components/build-types/table/types';
import { gmdateI18n } from '@wordpress/date';
import { __, sprintf } from '@wordpress/i18n';
import { Icon, plugins } from '@wordpress/icons';
import { createInterpolateElement } from '@wordpress/element';
/**
* Internal dependencies
@ -18,11 +19,13 @@ import Update from '../actions/update';
import StatusPopover from './status-popover';
import ActionsDropdownMenu from './actions-dropdown-menu';
import Version from './version';
import { renewUrl, subscribeUrl } from '../../../../utils/functions';
import { MARKETPLACE_COLLABORATION_PATH } from '../../../constants';
type StatusBadge = {
text: string;
level: StatusLevel;
explanation?: string;
explanation?: string | JSX.Element;
};
function getStatusBadges( subscription: Subscription ): StatusBadge[] {
@ -43,9 +46,37 @@ function getStatusBadges( subscription: Subscription ): StatusBadge[] {
badges.push( {
text: __( 'No subscription', 'woocommerce' ),
level: StatusLevel.Error,
explanation: __(
'To get updates and support for this extension, you need to purchase a new subscription, or else share or transfer a subscription for this extension from another account.',
'woocommerce'
explanation: createInterpolateElement(
__(
'To receive updates and support, please <purchase>purchase</purchase> a subscription or use a subscription from another account by <sharing>sharing</sharing> or <transferring>transferring</transferring>.',
'woocommerce'
),
{
purchase: (
<a
href={ subscribeUrl( subscription ) }
rel="nofollow noopener noreferrer"
>
renew
</a>
),
sharing: (
<a
href={ MARKETPLACE_COLLABORATION_PATH }
rel="nofollow noopener noreferrer"
>
sharing
</a>
),
transferring: (
<a
href={ MARKETPLACE_COLLABORATION_PATH }
rel="nofollow noopener noreferrer"
>
sharing
</a>
),
}
),
} );
@ -59,9 +90,37 @@ function getStatusBadges( subscription: Subscription ): StatusBadge[] {
badges.push( {
text: __( 'Expired', 'woocommerce' ),
level: StatusLevel.Error,
explanation: __(
'To receive updates and support, please renew your subscription.',
'woocommerce'
explanation: createInterpolateElement(
__(
'To receive updates and support, please <renew>renew</renew> this subscription or use a subscription from another account by <sharing>sharing</sharing> or <transferring>transferring</transferring>.',
'woocommerce'
),
{
renew: (
<a
href={ renewUrl( subscription ) }
rel="nofollow noopener noreferrer"
>
renew
</a>
),
sharing: (
<a
href={ MARKETPLACE_COLLABORATION_PATH }
rel="nofollow noopener noreferrer"
>
sharing
</a>
),
transferring: (
<a
href={ MARKETPLACE_COLLABORATION_PATH }
rel="nofollow noopener noreferrer"
>
sharing
</a>
),
}
),
} );
}

View File

@ -13,7 +13,7 @@ import { StatusLevel } from '../../types';
export default function StatusPopover( props: {
text: string;
level: StatusLevel;
explanation: string;
explanation: string | JSX.Element;
} ) {
const [ isVisible, setIsVisible ] = useState( false );
@ -39,7 +39,10 @@ export default function StatusPopover( props: {
<Icon icon={ info } size={ 16 } />
{ props.text }
{ shouldShowExplanation() && (
<Popover className="woocommerce-marketplace__my-subscriptions__popover">
<Popover
className="woocommerce-marketplace__my-subscriptions__popover"
position="top center"
>
{ props.explanation }
</Popover>
) }

View File

@ -14,7 +14,7 @@
.woocommerce-marketplace__product-list-title {
font-size: 16px;
font-weight: 600;
font-weight: 400;
}
}

View File

@ -12,7 +12,7 @@
flex: 1 0 0;
font-size: 20px;
font-style: normal;
font-weight: 500;
font-weight: 400;
margin-bottom: $medium-gap;
margin-top: $small-gap;

View File

@ -5,12 +5,15 @@ import apiFetch from '@wordpress/api-fetch';
import { __, sprintf } from '@wordpress/i18n';
import { dispatch } from '@wordpress/data';
import { Options } from '@wordpress/notices';
import { Icon } from '@wordpress/components';
/**
* Internal dependencies
*/
import { LOCALE } from '../../utils/admin-settings';
import { CategoryAPIItem } from '../components/category-selector/types';
import {
MARKETPLACE_CART_PATH,
MARKETPLACE_CATEGORY_API_PATH,
MARKETPLACE_HOST,
MARKETPLACE_SEARCH_API_PATH,
@ -346,6 +349,13 @@ function addNotice(
options
);
} else {
if ( ! options?.icon ) {
options = {
...options,
icon: <Icon icon="saved" />,
};
}
dispatch( 'core/notices' ).createSuccessNotice( message, options );
}
}
@ -373,6 +383,20 @@ const appendURLParams = (
return urlObject.toString();
};
const renewUrl = ( subscription: Subscription ): string => {
return appendURLParams( MARKETPLACE_CART_PATH, [
[ 'renew_product', subscription.product_id.toString() ],
[ 'product_key', subscription.product_key ],
[ 'order_id', subscription.order_id.toString() ],
] );
};
const subscribeUrl = ( subscription: Subscription ): string => {
return appendURLParams( MARKETPLACE_CART_PATH, [
[ 'add-to-cart', subscription.product_id.toString() ],
] );
};
export {
ProductGroup,
appendURLParams,
@ -386,4 +410,6 @@ export {
updateProduct,
addNotice,
removeNotice,
renewUrl,
subscribeUrl,
};

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Comment: Address design feedback.