From 51613c30201aaaafe951e5356e35346dd5ab008c Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Mon, 16 Dec 2024 16:00:27 +0100 Subject: [PATCH 1/3] Fix toggle animation issue --- .../SettingsBlocks/PaymentMethodItemBlock.js | 75 ++++++++----------- .../SettingsBlocks/PaymentMethodsBlock.js | 13 ++++ .../SettingsBlocks/SettingsBlock.js | 9 ++- 3 files changed, 49 insertions(+), 48 deletions(-) diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js index 3f3827f76..9dadf3023 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js @@ -5,56 +5,43 @@ import PaymentMethodIcon from '../PaymentMethodIcon'; import data from '../../../utils/data'; const PaymentMethodItemBlock = ( props ) => { - const [ paymentMethodState, setPaymentMethodState ] = useState(); + const [ isChecked, setIsChecked ] = useState( false ); const [ modalIsVisible, setModalIsVisible ] = useState( false ); const Modal = props?.modal; - const handleCheckboxState = ( checked ) => { - setPaymentMethodState( checked ? props.id : null ); - }; - return ( <> - ( -
-
- - - { props.title } - -
-

- { props.description } -

-
- - { Modal && ( -
- setModalIsVisible( true ) - } - > - { data().getImage( - 'icon-settings.svg' - ) } -
- ) } + +
+
+ + + { props.title } + +
+

+ { props.description } +

+
+ + { Modal && ( +
setModalIsVisible( true ) } + > + { data().getImage( 'icon-settings.svg' ) }
-
- ), - ] } - /> + ) } +
+
+ { Modal && modalIsVisible && ( ) } diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js index 68a18ad4b..28ed05f8c 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js @@ -1,7 +1,14 @@ +import { useState, useCallback } from '@wordpress/element'; import SettingsBlock from './SettingsBlock'; import PaymentMethodItemBlock from './PaymentMethodItemBlock'; const PaymentMethodsBlock = ( { paymentMethods, className = '' } ) => { + const [ selectedMethod, setSelectedMethod ] = useState( null ); + + const handleSelect = useCallback( ( methodId, isSelected ) => { + setSelectedMethod( isSelected ? methodId : null ); + }, [] ); + if ( paymentMethods.length === 0 ) { return null; } @@ -16,6 +23,12 @@ const PaymentMethodsBlock = ( { paymentMethods, className = '' } ) => { + handleSelect( paymentMethod.id, checked ) + } /> ) ) } diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js index 5e4985104..bb5de947a 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js @@ -1,13 +1,14 @@ -const SettingsBlock = ( { className, components = [] } ) => { +const SettingsBlock = ( { className, components = [], children } ) => { const blockClassName = [ 'ppcp-r-settings-block', className ].filter( Boolean ); return (
- { components.map( ( Component, index ) => ( - - ) ) } + { children || + components.map( ( Component, index ) => ( + + ) ) }
); }; From f32f30ef0aa67e2f4616bd3ac77a4eaaa3a10a5b Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Tue, 17 Dec 2024 11:50:32 +0100 Subject: [PATCH 2/3] Remove the components prop in favor of the native children prop to prevent unnecessary re-renders which are breaking component animations --- .../ReusableComponents/AccordionSection.js | 13 +- .../SettingsBlocks/AccordionSettingsBlock.js | 32 ++--- .../SettingsBlocks/ButtonSettingsBlock.js | 44 +++---- .../SettingsBlocks/FeatureSettingsBlock.js | 78 +++++------ .../SettingsBlocks/InputSettingsBlock.js | 36 ++--- .../SettingsBlocks/PaymentMethodsBlock.js | 31 ++--- .../SettingsBlocks/RadioSettingsBlock.js | 57 ++++---- .../SettingsBlocks/SelectSettingsBlock.js | 34 ++--- .../SettingsBlocks/SettingsBlock.js | 11 +- .../SettingsBlocks/ToggleSettingsBlock.js | 48 +++---- .../TabSettingsElements/Blocks/OrderIntent.js | 81 +++++------- .../Blocks/SavePaymentMethods.js | 123 ++++++++---------- .../Blocks/Troubleshooting.js | 54 ++++---- 13 files changed, 271 insertions(+), 371 deletions(-) diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/AccordionSection.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/AccordionSection.js index f5b071945..aff2d9997 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/AccordionSection.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/AccordionSection.js @@ -1,8 +1,6 @@ import { Icon } from '@wordpress/components'; import { chevronDown, chevronUp } from '@wordpress/icons'; - import classNames from 'classnames'; - import { useAccordionState } from '../../hooks/useAccordionState'; // Provide defaults for all layout components so the generic version just works. @@ -24,6 +22,13 @@ const DefaultDescription = ( { children } ) => (
{ children }
); +const AccordionContent = ( { isOpen, children } ) => { + if ( ! isOpen || ! children ) { + return null; + } + return
{ children }
; +}; + const Accordion = ( { title, id = '', @@ -65,9 +70,7 @@ const Accordion = ( { ) } - { isOpen && children && ( -
{ children }
- ) } + { children }
); }; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/AccordionSettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/AccordionSettingsBlock.js index 8a953c805..cf7f2cee4 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/AccordionSettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/AccordionSettingsBlock.js @@ -9,25 +9,19 @@ import { } from './SettingsBlockElements'; const SettingsAccordion = ( { title, description, children, ...props } ) => ( - ( - - { children } - - ), - ] } - /> + + + { children } + + ); export default SettingsAccordion; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ButtonSettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ButtonSettingsBlock.js index e2b2aeb53..e66223ba5 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ButtonSettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ButtonSettingsBlock.js @@ -3,32 +3,24 @@ import SettingsBlock from './SettingsBlock'; import { Header, Title, Action, Description } from './SettingsBlockElements'; const ButtonSettingsBlock = ( { title, description, ...props } ) => ( - ( - <> -
- { title } - { description } -
- - - - - ), - ] } - /> + +
+ { title } + { description } +
+ + + +
); export default ButtonSettingsBlock; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/FeatureSettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/FeatureSettingsBlock.js index 7b6010de6..2984e8074 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/FeatureSettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/FeatureSettingsBlock.js @@ -11,56 +11,42 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => { } return ( - <> - - { notes.map( ( note, index ) => ( - { note } - ) ) } - - + + { notes.map( ( note, index ) => ( + { note } + ) ) } + ); }; return ( - ( - <> -
- - { title } - { props.actionProps?.featureStatus && ( - <TitleBadge - { ...props.actionProps?.badge } - /> - ) } - - - { description } - { printNotes() } - -
- -
- { props.actionProps?.buttons.map( - ( button ) => ( - - ) - ) } -
-
- - ), - ] } - /> + +
+ + { title } + { props.actionProps?.featureStatus && ( + <TitleBadge { ...props.actionProps?.badge } /> + ) } + + + { description } + { printNotes() } + +
+ +
+ { props.actionProps?.buttons.map( ( button ) => ( + + ) ) } +
+
+
); }; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/InputSettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/InputSettingsBlock.js index 6f8a06e3b..3470e8b60 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/InputSettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/InputSettingsBlock.js @@ -42,28 +42,20 @@ const InputSettingsBlock = ( { order = DEFAULT_ELEMENT_ORDER, ...props } ) => ( - ( - <> - { order.map( ( elementKey ) => { - const RenderElement = ELEMENT_RENDERERS[ elementKey ]; - return RenderElement ? ( - - ) : null; - } ) } - - ), - ] } - /> + + { order.map( ( elementKey ) => { + const RenderElement = ELEMENT_RENDERERS[ elementKey ]; + return RenderElement ? ( + + ) : null; + } ) } + ); export default InputSettingsBlock; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js index 28ed05f8c..3ffb91051 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js @@ -16,25 +16,18 @@ const PaymentMethodsBlock = ( { paymentMethods, className = '' } ) => { return ( ( - <> - { paymentMethods.map( ( paymentMethod ) => ( - - handleSelect( paymentMethod.id, checked ) - } - /> - ) ) } - - ), - ] } - /> + > + { paymentMethods.map( ( paymentMethod ) => ( + + handleSelect( paymentMethod.id, checked ) + } + /> + ) ) } + ); }; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/RadioSettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/RadioSettingsBlock.js index 9519f127f..44270d874 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/RadioSettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/RadioSettingsBlock.js @@ -11,37 +11,32 @@ const RadioSettingsBlock = ( { ( - <> -
- { title } - { description } -
- { options.map( ( option ) => ( - - props.actionProps?.callback( - props.actionProps?.key, - newValue - ) - } - label={ option.label } - description={ option.description } - toggleAdditionalContent={ true } - > - { option.additionalContent } - - ) ) } - - ), - ] } - /> + > +
+ { title } + { description } +
+ { options.map( ( option ) => ( + + props.actionProps?.callback( + props.actionProps?.key, + newValue + ) + } + label={ option.label } + description={ option.description } + toggleAdditionalContent={ true } + > + { option.additionalContent } + + ) ) } +
); export default RadioSettingsBlock; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SelectSettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SelectSettingsBlock.js index acef1d29b..5436d0921 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SelectSettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SelectSettingsBlock.js @@ -35,27 +35,19 @@ const SelectSettingsBlock = ( { order = DEFAULT_ELEMENT_ORDER, ...props } ) => ( - ( - <> - { order.map( ( elementKey ) => { - const RenderElement = ELEMENT_RENDERERS[ elementKey ]; - return RenderElement ? ( - - ) : null; - } ) } - - ), - ] } - /> + + { order.map( ( elementKey ) => { + const RenderElement = ELEMENT_RENDERERS[ elementKey ]; + return RenderElement ? ( + + ) : null; + } ) } + ); export default SelectSettingsBlock; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js index bb5de947a..768fa9387 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/SettingsBlock.js @@ -1,16 +1,9 @@ -const SettingsBlock = ( { className, components = [], children } ) => { +const SettingsBlock = ( { className, children } ) => { const blockClassName = [ 'ppcp-r-settings-block', className ].filter( Boolean ); - return ( -
- { children || - components.map( ( Component, index ) => ( - - ) ) } -
- ); + return
{ children }
; }; export default SettingsBlock; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ToggleSettingsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ToggleSettingsBlock.js index 3e0c0eac6..b66536b00 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ToggleSettingsBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/ToggleSettingsBlock.js @@ -3,35 +3,25 @@ import SettingsBlock from './SettingsBlock'; import { Header, Title, Action, Description } from './SettingsBlockElements'; const ToggleSettingsBlock = ( { title, description, ...props } ) => ( - ( - - - props.actionProps?.callback( - props.actionProps?.key, - newValue - ) - } - /> - - ), - () => ( -
- { title && { title } } - { description && ( - { description } - ) } -
- ), - ] } - /> + + + + props.actionProps?.callback( + props.actionProps?.key, + newValue + ) + } + /> + +
+ { title && { title } } + { description && { description } } +
+
); export default ToggleSettingsBlock; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/OrderIntent.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/OrderIntent.js index 1d1b632fe..a53090ea1 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/OrderIntent.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/OrderIntent.js @@ -9,55 +9,40 @@ import { const OrderIntent = ( { updateFormValue, settings } ) => { return ( - ( - <> -
- - { __( - 'Order Intent', - 'woocommerce-paypal-payments' - ) } - - - { __( - 'Choose between immediate capture or authorization-only, with manual capture in the Order section.', - 'woocommerce-paypal-payments' - ) } - -
- - ), - () => ( - <> - + +
+ + { __( 'Order Intent', 'woocommerce-paypal-payments' ) } + + + { __( + 'Choose between immediate capture or authorization-only, with manual capture in the Order section.', + 'woocommerce-paypal-payments' + ) } + +
- - - ), - ] } - /> + + + +
); }; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/SavePaymentMethods.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/SavePaymentMethods.js index f10907c4c..aefa9f44c 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/SavePaymentMethods.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/SavePaymentMethods.js @@ -1,82 +1,73 @@ import { __, sprintf } from '@wordpress/i18n'; import { + Header, SettingsBlock, ToggleSettingsBlock, Title, Description, } from '../../../../ReusableComponents/SettingsBlocks'; -import { Header } from '../../../../ReusableComponents/SettingsBlocks/SettingsBlockElements'; const SavePaymentMethods = ( { updateFormValue, settings } ) => { return ( - ( - <> -
- - { __( - 'Save payment methods', - 'woocommerce-paypal-payments' - ) } - - - { __( - 'Securely store customers’ payment methods for future payments and subscriptions, simplifying checkout and enabling recurring transactions.', + +
+ + { __( + 'Save payment methods', + 'woocommerce-paypal-payments' + ) } + + + { __( + "Securely store customers' payment methods for future payments and subscriptions, simplifying checkout and enabling recurring transactions.", + 'woocommerce-paypal-payments' + ) } + +
+ + This will disable all Pay Later features and Alternative Payment Methods on your site.', 'woocommerce-paypal-payments' - ) } -
-
- - ), - () => ( - This will disable all Pay Later features and Alternative Payment Methods on your site.', - 'woocommerce-paypal-payments' - ), - 'https://woocommerce.com/document/woocommerce-paypal-payments/#pay-later', - 'https://woocommerce.com/document/woocommerce-paypal-payments/#alternative-payment-methods' - ), - } } - /> - } - actionProps={ { - value: settings.savePaypalAndVenmo, - callback: updateFormValue, - key: 'savePaypalAndVenmo', + ), + 'https://woocommerce.com/document/woocommerce-paypal-payments/#pay-later', + 'https://woocommerce.com/document/woocommerce-paypal-payments/#alternative-payment-methods' + ), } } /> - ), - () => ( - - ), - ] } - /> + } + actionProps={ { + value: settings.savePaypalAndVenmo, + callback: updateFormValue, + key: 'savePaypalAndVenmo', + } } + /> + + +
); }; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/Troubleshooting.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/Troubleshooting.js index f53a360c7..82cd635dc 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/Troubleshooting.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/Troubleshooting.js @@ -36,36 +36,30 @@ const Troubleshooting = ( { updateFormValue, settings } ) => { value: settings.logging, } } /> - ( - <> -
- - { __( - 'Subscribed PayPal webhooks', - 'woocommerce-paypal-payments' - ) } - - - { __( - 'The following PayPal webhooks are subscribed. More information about the webhooks is available in the', - 'woocommerce-paypal-payments' - ) }{ ' ' } - - { __( - 'Webhook Status documentation', - 'woocommerce-paypal-payments' - ) } - - . - -
- - - ), - ] } - /> + +
+ + { __( + 'Subscribed PayPal webhooks', + 'woocommerce-paypal-payments' + ) } + + + { __( + 'The following PayPal webhooks are subscribed. More information about the webhooks is available in the', + 'woocommerce-paypal-payments' + ) }{ ' ' } + + { __( + 'Webhook Status documentation', + 'woocommerce-paypal-payments' + ) } + + . + +
+ +
Date: Tue, 17 Dec 2024 11:56:38 +0100 Subject: [PATCH 3/3] Make the toggle state name a bit more descriptive --- .../SettingsBlocks/PaymentMethodItemBlock.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js index 9dadf3023..cdad46b3e 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodItemBlock.js @@ -5,7 +5,7 @@ import PaymentMethodIcon from '../PaymentMethodIcon'; import data from '../../../utils/data'; const PaymentMethodItemBlock = ( props ) => { - const [ isChecked, setIsChecked ] = useState( false ); + const [ toggleIsChecked, setToggleIsChecked ] = useState( false ); const [ modalIsVisible, setModalIsVisible ] = useState( false ); const Modal = props?.modal; @@ -28,8 +28,8 @@ const PaymentMethodItemBlock = ( props ) => {
{ Modal && (