From 85794e77ce2a492cdd3b926df8d8ff5fd8ea6211 Mon Sep 17 00:00:00 2001 From: Philipp Stracker Date: Wed, 15 Jan 2025 19:41:46 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84=20Improve=20the=20(broken)=20UI=20?= =?UTF-8?q?in=20the=20Styling-tab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/css/components/_reusable.scss | 1 + .../reusable-components/_hstack.scss | 20 +++ .../screens/settings/_tab-styling.scss | 51 ++---- .../Components/ReusableComponents/Fields.js | 161 +++++++++++------- .../Components/ReusableComponents/HStack.js | 26 +++ .../Components/Styling/SettingsPanel.js | 68 ++++---- .../resources/js/data/styling/constants.js | 6 + 7 files changed, 198 insertions(+), 135 deletions(-) create mode 100644 modules/ppcp-settings/resources/css/components/reusable-components/_hstack.scss create mode 100644 modules/ppcp-settings/resources/js/Components/ReusableComponents/HStack.js diff --git a/modules/ppcp-settings/resources/css/components/_reusable.scss b/modules/ppcp-settings/resources/css/components/_reusable.scss index 4d4f5c1ba..2de887f57 100644 --- a/modules/ppcp-settings/resources/css/components/_reusable.scss +++ b/modules/ppcp-settings/resources/css/components/_reusable.scss @@ -4,6 +4,7 @@ @import './reusable-components/busy-state'; @import './reusable-components/button'; @import './reusable-components/fields'; +@import './reusable-components/hstack'; @import './reusable-components/navigation'; @import './reusable-components/onboarding-header'; @import './reusable-components/payment-method-icons'; diff --git a/modules/ppcp-settings/resources/css/components/reusable-components/_hstack.scss b/modules/ppcp-settings/resources/css/components/reusable-components/_hstack.scss new file mode 100644 index 000000000..e55584d1c --- /dev/null +++ b/modules/ppcp-settings/resources/css/components/reusable-components/_hstack.scss @@ -0,0 +1,20 @@ +.components-flex { + display: flex; + -webkit-box-align: stretch; + align-items: stretch; + flex-direction: column; + -webkit-box-pack: center; + justify-content: center; + + .components-h-stack { + flex-direction: row; + justify-content: flex-start; + gap: 32px; + } + + // Fix layout for checkboxes inside a flex-stack. + .components-checkbox-control >.components-base-control__field > .components-flex { + flex-direction: row; + gap: 12px; + } +} diff --git a/modules/ppcp-settings/resources/css/components/screens/settings/_tab-styling.scss b/modules/ppcp-settings/resources/css/components/screens/settings/_tab-styling.scss index 87472e377..61534cc04 100644 --- a/modules/ppcp-settings/resources/css/components/screens/settings/_tab-styling.scss +++ b/modules/ppcp-settings/resources/css/components/screens/settings/_tab-styling.scss @@ -27,6 +27,16 @@ $width-settings-panel: 422px; padding-bottom: 24px; margin-bottom: 28px; border-bottom: 1px solid var(--color-separators); + + &:last-child { + padding-bottom: 0; + margin-bottom: 0; + border-bottom-style: none; + } + } + + .components-radio-control__option { + min-width: 100px; } } @@ -65,46 +75,7 @@ $width-settings-panel: 422px; color: $color-black; } } - - .components-flex { - gap: 12px; - } - } - - &__payment-method-checkboxes { - display: flex; - flex-direction: column; - gap: 24px; } } - -.ppcp-r { - &__horizontal-control { - .components-flex { - flex-direction: row; - justify-content: flex-start; - gap: 32px; - } - - - .components-radio-control { - &__option { - gap: 12px; - - input { - margin: 0; - } - - label { - @include font(13, 20, 400); - color: $color-black; - } - } - - input { - margin: 0; - } - } - } - // */ +//*/ } diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/Fields.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/Fields.js index 74336951f..862e057bb 100644 --- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/Fields.js +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/Fields.js @@ -1,107 +1,136 @@ import { CheckboxControl } from '@wordpress/components'; +import classNames from 'classnames'; -export const PayPalCheckbox = ( props ) => { - let isChecked = null; +export const PayPalCheckbox = ( { + currentValue, + label, + value, + checked = null, + disabled = null, + changeCallback, +} ) => { + let isChecked = checked; - if ( Array.isArray( props.currentValue ) ) { - isChecked = props.currentValue.includes( props.value ); - } else { - isChecked = props.currentValue; + if ( null === isChecked ) { + if ( Array.isArray( currentValue ) ) { + isChecked = currentValue.includes( value ); + } else { + isChecked = currentValue; + } } + const onChange = ( newState ) => { + let newValue; + + if ( ! Array.isArray( currentValue ) ) { + newValue = newState; + } else if ( newState ) { + newValue = [ ...currentValue, value ]; + } else { + newValue = currentValue.filter( + ( optionValue ) => optionValue !== value + ); + } + + changeCallback( newValue ); + }; + return (
+ { /* todo: Can we remove the wrapper div? */ } - handleCheckboxState( checked, props ) - } + disabled={ disabled } + onChange={ onChange } />
); }; -export const PayPalCheckboxGroup = ( props ) => { - const renderCheckboxGroup = () => { - return props.value.map( ( checkbox ) => { - return ( - - ); - } ); - }; +export const CheckboxGroup = ( { options, value, onChange } ) => ( + <> + { options.map( ( checkbox ) => ( + + ) ) } + +); - return <>{ renderCheckboxGroup() }; -}; - -export const PayPalRdb = ( props ) => { +export const PayPalRdb = ( { + id, + name, + value, + currentValue, + handleRdbState, +} ) => { return (
+ { /* todo: Can we remove the wrapper div? */ } props.handleRdbState( props.value ) } + id={ id } + checked={ value === currentValue } + name={ name } + value={ value } + onChange={ () => handleRdbState( value ) } />
); }; -export const PayPalRdbWithContent = ( props ) => { - const className = [ 'ppcp-r__radio-wrapper' ]; - - if ( props?.className ) { - className.push( props.className ); - } +export const PayPalRdbWithContent = ( { + className, + id, + name, + label, + description, + value, + currentValue, + handleRdbState, + toggleAdditionalContent, + children, +} ) => { + const wrapperClasses = classNames( 'ppcp-r__radio-wrapper', className ); return (
-
- +
+ +
- - { props.description && ( + + { description && (

) }

- { props?.toggleAdditionalContent && - props.children && - props.value === props.currentValue && ( -
- { props.children } -
- ) } + { toggleAdditionalContent && children && value === currentValue && ( +
+ { children } +
+ ) }
); }; - -export const handleCheckboxState = ( checked, props ) => { - let newValue = null; - if ( ! Array.isArray( props.currentValue ) ) { - newValue = checked; - } else if ( checked ) { - newValue = [ ...props.currentValue, props.value ]; - } else { - newValue = props.currentValue.filter( - ( value ) => value !== props.value - ); - } - props.changeCallback( newValue ); -}; diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/HStack.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/HStack.js new file mode 100644 index 000000000..2c54ac7da --- /dev/null +++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/HStack.js @@ -0,0 +1,26 @@ +/** + * Temporary component, until the experimental HStack block editor component is stable. + * + * @see https://wordpress.github.io/gutenberg/?path=/docs/components-experimental-hstack--docs + * @file + */ +import classNames from 'classnames'; + +const HStack = ( { className, spacing = 3, children } ) => { + const wrapperClass = classNames( + 'components-flex components-h-stack', + className + ); + + const styles = { + gap: `calc(${ 4 * spacing }px)`, + }; + + return ( +
+ { children } +
+ ); +}; + +export default HStack; diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Styling/SettingsPanel.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Styling/SettingsPanel.js index e739ab629..f357bb287 100644 --- a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Styling/SettingsPanel.js +++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Styling/SettingsPanel.js @@ -4,7 +4,8 @@ import { RadioControl, SelectControl } from '@wordpress/components'; // Dummy hook. import { useStylingLocation, useStylingProps } from '../../Tabs/TabStyling'; -import { PayPalCheckboxGroup } from '../../../../ReusableComponents/Fields'; +import { CheckboxGroup } from '../../../../ReusableComponents/Fields'; +import HStack from '../../../../ReusableComponents/HStack'; import LocationSelector from './LocationSelector'; import StylingSection from './StylingSection'; @@ -30,6 +31,7 @@ const SettingsPanel = () => { export default SettingsPanel; // ----- + const SectionPaymentMethods = ( { location } ) => { const { paymentMethods, setPaymentMethods, paymentMethodChoices } = useStylingProps( location ); @@ -39,11 +41,13 @@ const SectionPaymentMethods = ( { location } ) => { title={ __( 'Payment Methods', 'woocommerce-paypal-payments' ) } className="payment-methods" > - + + + ); }; @@ -61,12 +65,13 @@ const SectionButtonLayout = ( { location } ) => { className="button-layout" title={ __( 'Button Layout', 'woocommerce-paypal-payments' ) } > - + + + ); }; @@ -79,12 +84,13 @@ const SectionButtonShape = ( { location } ) => { title={ __( 'Shape', 'woocommerce-paypal-payments' ) } className="button-shape" > - + + + ); }; @@ -93,10 +99,11 @@ const SectionButtonLabel = ( { location } ) => { const { label, setLabel, labelChoices } = useStylingProps( location ); return ( - + { const { color, setColor, colorChoices } = useStylingProps( location ); return ( - + { title={ __( 'Tagline', 'woocommerce-paypal-payments' ) } className="tagline" > - + + + ); }; diff --git a/modules/ppcp-settings/resources/js/data/styling/constants.js b/modules/ppcp-settings/resources/js/data/styling/constants.js index 395d80cdb..f21ac7adf 100644 --- a/modules/ppcp-settings/resources/js/data/styling/constants.js +++ b/modules/ppcp-settings/resources/js/data/styling/constants.js @@ -147,6 +147,12 @@ export const STYLING_SHAPES = { }; export const STYLING_PAYMENT_METHODS = { + paypal: { + value: '', + label: __( 'PayPal', 'woocommerce-paypal-payments' ), + checked: true, + disabled: true, + }, venmo: { value: 'venmo', label: __( 'Venmo', 'woocommerce-paypal-payments' ),