On-/offboarding copy updates (#39055)

* Change the modal's description test in the first step of the product block editor tour

* Change the modal's description text in the first step of the product block editor guide

* Change the modal's description text in the second step of the product block editor guide

* Change the modal's title and description text in the third step of the product block editor guide

* Change the modal's description text in the four step of the product block editor guide

* Enhance the Options menu of the product block editor

* Add slide up animation and translucent background to the feedback bottom bar

* Change de CES's modal heading text in the product block editor

* Change the notice message after the feedback is being sent from the CES Modals

* Enhance leave feedback modal checkbox labels

* Change leave feedback modal submit button text

* Show success notice after submit the leave feedback modal

* Add changelog files

* Change the illustration in the first step of the feature tour

* Change the modal's title and description text in the first step of the product block editor tour for old users

* Change the modal's title and description text in the first step of the product block editor guide for old users

* Change the modal's title and description text in the third step of the product block editor guide for old users

* Fix unit tests

* Change the customer effort score changelog description

* Change footer forward button to primary and backward button to tertiary in the tour guide modal
This commit is contained in:
Maikel David Pérez Gómez 2023-07-10 14:51:55 -04:00 committed by GitHub
parent 1cd947a320
commit 96c0c5bd74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 213 additions and 188 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Fixing the onsubmit_label prop from SHOW_CES_MODAL action incorreclty named as onSubmitLabel

View File

@ -28,7 +28,7 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
action: action.surveyProps.action,
showDescription: action.surveyProps.showDescription,
title: action.surveyProps.title,
onSubmitLabel: action.onSubmitLabel,
onSubmitLabel: action.onsubmit_label,
firstQuestion: action.surveyProps.firstQuestion,
secondQuestion: action.surveyProps.secondQuestion,
onSubmitNoticeProps: action.onSubmitNoticeProps || {},

View File

@ -0,0 +1,4 @@
Significance: minor
Type: enhancement
New product block editor modal text enhancements

View File

@ -53,7 +53,7 @@ export function FeedbackBar( { product }: FeedbackBarProps ) {
action: PRODUCT_EDITOR_FEEDBACK_CES_ACTION,
showDescription: false,
title: __(
"How's your experience with the new product form?",
'What do you think of the new product form?',
'woocommerce'
),
firstQuestion: __(
@ -65,7 +65,7 @@ export function FeedbackBar( { product }: FeedbackBarProps ) {
'woocommerce'
),
onsubmitLabel: __(
"Thanks for the feedback. We'll put it to good use!",
"Thanks for the feedback — we'll put it to good use!",
'woocommerce'
),
shouldShowComments: () => false,
@ -174,7 +174,6 @@ export function FeedbackBar( { product }: FeedbackBarProps ) {
{},
{
type: 'snackbar',
icon: <span>🌟</span>,
}
);
};
@ -201,38 +200,40 @@ export function FeedbackBar( { product }: FeedbackBarProps ) {
<>
{ shouldShowFeedbackBar && (
<div className="woocommerce-product-mvp-ces-footer">
<Pill>Beta</Pill>
<div className="woocommerce-product-mvp-ces-footer__message">
{ createInterpolateElement(
__(
'How is your experience with the new product form? <span><shareButton>Share feedback</shareButton> or <turnOffButton>turn it off</turnOffButton></span>',
'woocommerce'
),
{
span: (
<span className="woocommerce-product-mvp-ces-footer__message-buttons" />
<div className="woocommerce-product-mvp-ces-footer__body">
<Pill>Beta</Pill>
<div className="woocommerce-product-mvp-ces-footer__message">
{ createInterpolateElement(
__(
'How is your experience with the new product form? <span><shareButton>Share feedback</shareButton> or <turnOffButton>turn it off</turnOffButton></span>',
'woocommerce'
),
shareButton: (
<Button
variant="link"
onClick={ onShareFeedbackClick }
/>
),
turnOffButton: (
<Button
onClick={ onTurnOffEditorClick }
variant="link"
/>
),
}
) }
{
span: (
<span className="woocommerce-product-mvp-ces-footer__message-buttons" />
),
shareButton: (
<Button
variant="link"
onClick={ onShareFeedbackClick }
/>
),
turnOffButton: (
<Button
onClick={ onTurnOffEditorClick }
variant="link"
/>
),
}
) }
</div>
<Button
className="woocommerce-product-mvp-ces-footer__close-button"
icon={ closeSmall }
label={ __( 'Hide this message', 'woocommerce' ) }
onClick={ onHideFeedbackBarClick }
></Button>
</div>
<Button
className="woocommerce-product-mvp-ces-footer__close-button"
icon={ closeSmall }
label={ __( 'Hide this message', 'woocommerce' ) }
onClick={ onHideFeedbackBarClick }
></Button>
</div>
) }
</>

View File

@ -1,20 +1,38 @@
$gutenberg-blue: var(--wp-admin-theme-color);
.woocommerce-product-mvp-ces-footer {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
// the left/right padding is set to this to match the padding of
// .block-editor-block-list__layout.is-root-container and
// .editor-styles-wrapper combined
padding: $gap calc(2 * $gap + $gap-small);
gap: $gap;
@keyframes slide-up {
0% {
bottom: -60px;
}
100% {
bottom: 0;
}
}
@include breakpoint(">782px") {
padding: $gap 0;
max-width: 650px;
margin: 0 auto;
.woocommerce-product-mvp-ces-footer {
position: fixed;
animation: slide-up 0.5s forwards;
width: 100%;
border-top: 1px solid var(--gutenberg-gray-100, #f0f0f0);
background: rgba(255, 255, 255, 0.5);
backdrop-filter: blur(6px);
&__body {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
// the left/right padding is set to this to match the padding of
// .block-editor-block-list__layout.is-root-container and
// .editor-styles-wrapper combined
padding: $gap calc(2 * $gap + $gap-small);
gap: $gap;
@include breakpoint(">782px") {
padding: $gap 0;
max-width: 650px;
margin: 0 auto;
}
}
.woocommerce-pill {

View File

@ -16,6 +16,7 @@ import {
import { FeedbackModal } from '@woocommerce/customer-effort-score';
import { Text } from '@woocommerce/experimental';
import { __ } from '@wordpress/i18n';
import { useDispatch } from '@wordpress/data';
/**
* Provides a modal requesting customer feedback.
@ -56,13 +57,13 @@ function ProductMVPFeedbackModal( {
},
{
key: 'difficult-to-use',
label: __( 'It is difficult to use', 'woocommerce' ),
label: __( "It's difficult to use", 'woocommerce' ),
checked: difficultToUse,
onChange: setDifficultToUse,
},
{
key: 'slow-buggy-or-broken',
label: __( 'It is slow, buggy, or broken', 'woocommerce' ),
label: __( "It's slow, buggy, or broken", 'woocommerce' ),
checked: slowBuggyOrBroken,
onChange: setSlowBuggyOrBroken,
},
@ -79,8 +80,16 @@ function ProductMVPFeedbackModal( {
.filter( ( checkbox ) => checkbox.checked )
.map( ( checkbox ) => checkbox.key );
const { createSuccessNotice } = useDispatch( 'core/notices' );
const onSendFeedback = () => {
recordScoreCallback( checked, comments, email );
createSuccessNotice(
__(
"Thanks for the feedback — we'll put it to good use!",
'woocommerce'
)
);
};
const optionalElement = (
@ -98,7 +107,7 @@ function ProductMVPFeedbackModal( {
onSubmit={ onSendFeedback }
onModalClose={ onCloseModal }
isSubmitButtonDisabled={ ! checked.length }
submitButtonLabel={ __( 'Send feedback', 'woocommerce' ) }
submitButtonLabel={ __( 'Send', 'woocommerce' ) }
cancelButtonLabel={ __( 'Skip', 'woocommerce' ) }
className="woocommerce-product-mvp-feedback-modal"
>

View File

@ -1,8 +1,9 @@
/**
* External dependencies
*/
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen, fireEvent, act } from '@testing-library/react';
import { createElement } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
/**
* Internal dependencies
@ -11,7 +12,22 @@ import { ProductMVPFeedbackModal } from '../index';
const mockRecordScoreCallback = jest.fn();
jest.mock( '@wordpress/data', () => ( {
...jest.requireActual( '@wordpress/data' ),
useDispatch: jest.fn(),
} ) );
describe( 'ProductMVPFeedbackModal', () => {
const createSuccessNotice = jest.fn();
beforeEach( () => {
( useDispatch as jest.Mock ).mockReturnValue( { createSuccessNotice } );
} );
afterEach( () => {
jest.resetAllMocks();
} );
it( 'should close the ProductMVPFeedback modal when skip button pressed', async () => {
render(
<ProductMVPFeedbackModal
@ -33,9 +49,7 @@ describe( 'ProductMVPFeedbackModal', () => {
// Wait for the modal to render.
await screen.findByRole( 'dialog' );
fireEvent.click( screen.getByRole( 'checkbox', { name: /other/i } ) );
fireEvent.click(
screen.getByRole( 'button', { name: /Send feedback/i } )
);
fireEvent.click( screen.getByRole( 'button', { name: /Send/i } ) );
} );
it( 'should call the function sent as recordScoreCallback with the checked options', async () => {
render(
@ -45,7 +59,15 @@ describe( 'ProductMVPFeedbackModal', () => {
);
// Wait for the modal to render.
await screen.findByRole( 'dialog' );
fireEvent.click( screen.getByRole( 'checkbox', { name: /other/i } ) );
act( () => {
fireEvent.click(
screen.getByRole( 'checkbox', { name: /other/i } )
);
} );
act( () => {
fireEvent.click( screen.getByRole( 'button', { name: /Send/i } ) );
} );
expect( mockRecordScoreCallback ).toHaveBeenCalledWith(
[ 'other' ],
'',

View File

@ -31,7 +31,7 @@ export const AboutTheEditorMenuItem = ( {
icon={ <Icon icon={ info } /> }
iconPosition="right"
>
{ __( 'About the editor…', 'woocommerce' ) }
{ __( 'About the form…', 'woocommerce' ) }
</MenuItem>
{ isGuideOpen && (
<BlockEditorGuide

View File

@ -35,7 +35,7 @@ export const FeedbackMenuItem = ( { onClick }: { onClick: () => void } ) => {
action: 'new_product',
showDescription: false,
title: __(
"How's your experience with the new product form?",
'What do you think of the new product form?',
'woocommerce'
),
firstQuestion: __(
@ -46,6 +46,10 @@ export const FeedbackMenuItem = ( { onClick }: { onClick: () => void } ) => {
"The product editing screen's functionality meets my needs",
'woocommerce'
),
onsubmitLabel: __(
"Thanks for the feedback — we'll put it to good use!",
'woocommerce'
),
getExtraFieldsToBeShown: (
values: {
email?: string;
@ -161,7 +165,6 @@ export const FeedbackMenuItem = ( { onClick }: { onClick: () => void } ) => {
},
{
type: 'snackbar',
icon: <span>🌟</span>,
},
{
block_editor: isDescendantOf( 'product-block-editor' ),

View File

@ -1,6 +1,8 @@
/**
* External dependencies
*/
import { MenuGroup } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import {
__experimentalProductMVPFeedbackModalContainer as ProductMVPFeedbackModalContainer,
__experimentalWooProductMoreMenuItem as WooProductMoreMenuItem,
@ -46,27 +48,31 @@ const MoreMenuFill = ( { onClose }: { onClose: () => void } ) => {
return (
<>
<FeedbackMenuItem
onClick={ () => {
recordClick( 'feedback' );
onClose();
} }
/>
<ClassicEditorMenuItem
productId={ id }
onClick={ () => {
recordClick( 'classic_editor' );
onClose();
} }
/>
<AboutTheEditorMenuItem
onClick={ () => {
recordClick( 'about' );
} }
onCloseGuide={ () => {
onClose();
} }
/>
<MenuGroup label={ __( 'New product form (Beta)', 'woocommerce' ) }>
<AboutTheEditorMenuItem
onClick={ () => {
recordClick( 'about' );
} }
onCloseGuide={ () => {
onClose();
} }
/>
<FeedbackMenuItem
onClick={ () => {
recordClick( 'feedback' );
onClose();
} }
/>
</MenuGroup>
<MenuGroup>
<ClassicEditorMenuItem
productId={ id }
onClick={ () => {
recordClick( 'classic_editor' );
onClose();
} }
/>
</MenuGroup>
</>
);
};

View File

@ -45,50 +45,33 @@ interface BlockEditorGuideProps {
onCloseGuide: ( currentPage: number, origin: 'close' | 'finish' ) => void;
}
const BlockEditorGuide = ( {
isNewUser = false,
onCloseGuide,
}: BlockEditorGuideProps ) => {
const BlockEditorGuide = ( { onCloseGuide }: BlockEditorGuideProps ) => {
const pagesConfig = [
{
heading: isNewUser
? __( 'Fresh and modern interface', 'woocommerce' )
: __( 'Refreshed, streamlined interface', 'woocommerce' ),
text: isNewUser
? __(
'Using the product form means less clicking around. Product details are neatly grouped by tabs, so you always know where to go.',
'woocommerce'
)
: __(
'Experience a simpler, more focused interface with a modern design that enhances usability.',
'woocommerce'
),
},
{
heading: __( 'Content-rich product descriptions', 'woocommerce' ),
heading: __( 'Fresh and modern interface', 'woocommerce' ),
text: __(
'Create compelling product pages with blocks, media, images, videos, and any content you desire to engage customers.',
'Everything you need to create and sell your products, all in one place. From photos and descriptions to pricing and inventory, all of your product settings can be found here.',
'woocommerce'
),
},
{
heading: isNewUser
? __( 'Speed & performance', 'woocommerce' )
: __( 'Improved speed & performance', 'woocommerce' ),
text: isNewUser
? __(
'Create a product from start to finish without page reloads. Our modern technology ensures reliability and lightning-fast performance.',
'woocommerce'
)
: __(
'Enjoy a seamless experience without page reloads. Our modern technology ensures reliability and lightning-fast performance.',
'woocommerce'
),
heading: __( 'Content-rich product descriptions', 'woocommerce' ),
text: __(
"Show off what's great about your products and engage your customers with content-rich product descriptions. Add images, videos, and any other content they might need to make a purchase.",
'woocommerce'
),
},
{
heading: __( 'Lightning fast performance ', 'woocommerce' ),
text: __(
'Get your products listed and available for purchase in no time! Our modern technology ensures a reliable and streamlined experience.',
'woocommerce'
),
},
{
heading: __( 'More features are on the way', 'woocommerce' ),
text: __(
'While we currently support physical products, exciting updates are coming to accommodate more types, like digital products, variations, and more. Stay tuned!',
"We're actively working on adding more features to the product form, including the ability to add digital products, variations, and more. Watch this space!",
'woocommerce'
),
},

View File

@ -42,14 +42,14 @@ const BlockEditorTour = ( { shouldTourBeShown, dismissModal }: Props ) => {
return {
heading: isNewUser
? __( 'Meet the product editing form', 'woocommerce' )
: __( 'A new way to edit your products', 'woocommerce' ),
: __( 'Welcome to the new product form!', 'woocommerce' ),
description: isNewUser
? __(
"Discover the form's unique features designed to help you make this product stand out.",
"Discover the product form's unique features with a quick overview of what's included.",
'woocommerce'
)
: __(
'Introducing the upgraded experience designed to help you create and edit products easier.',
"Discover its new features and improvements with a quick overview of what's included.",
'woocommerce'
),
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -1,31 +0,0 @@
<svg width="312" height="222" viewBox="0 0 312 222" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="312" height="222" fill="#F6F7F7"/>
<path d="M87.6168 96L92 96L92 135L92 174L87.6168 174C87.6168 156.805 82.1737 139.763 77.5075 139.763C66.1856 139.763 60.3578 146.362 52.0988 146.362C47.2305 146.362 40 144.478 40 135C40 125.527 47.2305 123.638 52.0988 123.638C60.3578 123.638 66.1856 130.237 77.5075 130.237C82.1737 130.237 87.6168 113.195 87.6168 96ZM45.7754 135C45.7754 137.175 47.5763 138.94 49.7949 138.94C52.0135 138.94 53.8144 137.175 53.8144 135C53.8144 132.825 52.0135 131.06 49.7949 131.06C47.5763 131.06 45.7754 132.825 45.7754 135Z" fill="#FF6BBB"/>
<path d="M91.8418 96L174.842 96L174.842 135L174.842 174L91.8418 174L91.8418 96Z" fill="#966CCF"/>
<g style="mix-blend-mode:soft-light">
<path d="M175 174L153.339 174C128.943 171.352 104 165.176 104 157.441C104 145.4 131.103 147.776 131.103 139.435C131.103 131.093 117.909 135.078 117.909 125.438C117.909 115.797 152.495 113 174.984 113L174.984 174L175 174Z" fill="white"/>
</g>
<rect x="193" y="49" width="51" height="51" rx="25.5" fill="#FFC350"/>
<rect x="193" y="49" width="51" height="51" rx="25.5" fill="url(#paint0_linear_1997_17544)"/>
<path d="M219.619 84.0169L217.458 78.7849H206.589L204.428 84.0169H203.348L211.471 64.5217H212.58L220.703 84.0169H219.622H219.619ZM212.024 65.6027L206.938 77.9082H217.106L212.02 65.6027H212.024Z" fill="white"/>
<path d="M232.944 84.0169V82.2918C231.627 83.7247 230.051 84.3657 228.065 84.3657C225.581 84.3657 223.127 82.6688 223.127 79.6585C223.127 76.6481 225.552 74.9512 228.065 74.9512C230.054 74.9512 231.631 75.5954 232.944 77.0252V73.8388C232.944 71.5575 231.131 70.3319 228.97 70.3319C227.129 70.3319 225.757 70.9761 224.44 72.5536L223.768 71.9691C225.141 70.3602 226.602 69.5432 228.97 69.5432C231.747 69.5432 233.82 70.9478 233.82 73.8105V84.0106H232.944V84.0169ZM232.944 81.415V77.9082C231.863 76.4753 230.139 75.7462 228.298 75.7462C225.725 75.7462 224.092 77.4714 224.092 79.6616C224.092 81.8518 225.728 83.577 228.298 83.577C230.139 83.577 231.863 82.848 232.944 81.415Z" fill="white"/>
<g style="mix-blend-mode:multiply">
<rect x="92" y="49" width="83" height="28" rx="14" fill="#007CBA"/>
<rect x="92" y="49" width="83" height="28" rx="14" fill="url(#paint1_linear_1997_17544)" fill-opacity="0.4"/>
<path d="M160.655 70.3093C164.882 70.3093 168.309 66.8822 168.309 62.6547C168.309 58.4271 164.882 55 160.655 55C156.427 55 153 58.4271 153 62.6547C153 66.8822 156.427 70.3093 160.655 70.3093Z" fill="white"/>
</g>
<circle cx="218" cy="167" r="6.44257" transform="rotate(-90 218 167)" stroke="#BBBBBB" stroke-width="1.11486"/>
<circle cx="218" cy="121" r="6.44257" transform="rotate(-90 218 121)" stroke="#BBBBBB" stroke-width="1.11486"/>
<ellipse cx="218" cy="144" rx="7" ry="7" transform="rotate(-90 218 144)" fill="#007CBA"/>
<circle cx="218" cy="144" r="10.4426" transform="rotate(-90 218 144)" stroke="#BBBBBB" stroke-width="1.11486"/>
<defs>
<linearGradient id="paint0_linear_1997_17544" x1="207.845" y1="52.0186" x2="224.58" y2="97.7763" gradientUnits="userSpaceOnUse">
<stop stop-color="#FBA500"/>
<stop offset="1" stop-color="#FBA500" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_1997_17544" x1="94" y1="55" x2="116.529" y2="74.1452" gradientUnits="userSpaceOnUse">
<stop stop-color="#2508D3"/>
<stop offset="1" stop-color="#2508D3" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -6,7 +6,7 @@
background-size: cover;
&-1 {
background-image: url(./images/guide-1.svg);
background-image: url(./images/guide-1.png);
}
&-2 {
@ -78,6 +78,4 @@
}
}
}
}

View File

@ -11,6 +11,7 @@ import { Modal, Button } from '@wordpress/components';
*/
import PageControl from './page-control';
import type { GuideProps } from './types';
import './style.scss';
/*
* This component was copied from @wordpress/components since we needed
@ -90,6 +91,7 @@ function Guide( {
{ canGoBack && (
<Button
className="components-guide__back-button"
variant="tertiary"
onClick={ goBack }
>
{ __( 'Previous', 'woocommerce' ) }
@ -98,6 +100,7 @@ function Guide( {
{ canGoForward && (
<Button
className="components-guide__forward-button"
variant="primary"
onClick={ goForward }
>
{ __( 'Next', 'woocommerce' ) }
@ -106,6 +109,7 @@ function Guide( {
{ ! canGoForward && (
<Button
className="components-guide__finish-button"
variant="primary"
href={ finishButtonLink }
target={ finishButtonLink ? '_blank' : undefined }
rel={ finishButtonLink ? 'noopener' : undefined }

View File

@ -63,6 +63,43 @@
padding: 0 $grid-unit-40;
position: relative;
width: 100%;
.components-button {
&.components-guide__back-button,
&.components-guide__forward-button,
&.components-guide__finish-button {
height: 30px;
position: absolute;
font-weight: inherit;
&.is-primary {
color: var(--wp-components-color-accent-inverted, #fff);
}
&:hover {
text-decoration: none;
}
}
&.components-guide__back-button,
&.components-guide__forward-button {
font-size: $default-font-size;
padding: 4px 2px;
&.has-text svg {
margin: 0;
}
}
&.components-guide__back-button {
left: $grid-unit-40;
}
&.components-guide__forward-button,
&.components-guide__finish-button {
right: $grid-unit-40;
}
}
}
&__page-control {
@ -88,45 +125,8 @@
height: 80vh;
max-height: 575px;
@media ( max-width: $break-small ) {
@media (max-width: $break-small) {
margin: auto;
max-width: calc(100vw - #{$grid-unit-20} * 2);
}
}
.components-button {
&.components-guide__back-button,
&.components-guide__forward-button,
&.components-guide__finish-button {
height: 30px;
position: absolute;
}
&.components-guide__back-button,
&.components-guide__forward-button {
font-size: $default-font-size;
padding: 4px 2px;
&.has-text svg {
margin: 0;
}
&:hover {
text-decoration: underline;
}
}
&.components-guide__back-button {
left: $grid-unit-40;
}
&.components-guide__forward-button {
right: $grid-unit-40;
color: #1386bf;
font-weight: bold;
}
&.components-guide__finish-button {
right: $grid-unit-40;
}
}

View File

@ -0,0 +1,4 @@
Significance: minor
Type: enhancement
New product block editor modal text enhancements