From 2d30b89e21fc4ccb882fb437838c0bafe5fe36ce Mon Sep 17 00:00:00 2001 From: Mike Moore Date: Mon, 27 Jan 2025 13:58:10 -0500 Subject: [PATCH] Better responsive handling --- .../checkout/blocks/payment-method-label.js | 3 +- .../payment-methods-logos/logo-popover.tsx | 38 +++++------ .../blocks/payment-methods-logos/style.scss | 13 ++-- client/checkout/classic/event-handlers.js | 68 +++++++++++-------- client/checkout/classic/style.scss | 18 +++++ 5 files changed, 82 insertions(+), 58 deletions(-) diff --git a/client/checkout/blocks/payment-method-label.js b/client/checkout/blocks/payment-method-label.js index 6b5918de763..ecc339b0a32 100644 --- a/client/checkout/blocks/payment-method-label.js +++ b/client/checkout/blocks/payment-method-label.js @@ -40,8 +40,7 @@ const paymentMethods = [ ]; const breakpointConfigs = [ { breakpoint: 550, maxElements: 2 }, - { breakpoint: 833, maxElements: 4 }, - { breakpoint: 960, maxElements: 2 }, + { breakpoint: 330, maxElements: 1 }, ]; const bnplMethods = [ 'affirm', 'afterpay_clearpay', 'klarna' ]; diff --git a/client/checkout/blocks/payment-methods-logos/logo-popover.tsx b/client/checkout/blocks/payment-methods-logos/logo-popover.tsx index f1ebde5c300..36d7aa1c761 100644 --- a/client/checkout/blocks/payment-methods-logos/logo-popover.tsx +++ b/client/checkout/blocks/payment-methods-logos/logo-popover.tsx @@ -37,31 +37,19 @@ export const LogoPopover: React.FC< LogoPopoverProps > = ( { return; } - // Get the most up-to-date anchor rect - const anchorRect = anchor.getBoundingClientRect(); + const label = anchor.closest( 'label' ); + if ( ! label ) return; - // Temporarily make the popover visible to get correct dimensions - popover.style.visibility = 'hidden'; - popover.style.display = 'block'; - const popoverRect = popover.getBoundingClientRect(); - popover.style.display = ''; - popover.style.visibility = ''; - - const offset = 7; - const left = anchorRect.left; - // Position the popover above the anchor - const top = anchorRect.top - popoverRect.height - offset; + const labelRect = label.getBoundingClientRect(); + const labelStyle = window.getComputedStyle( label ); + const labelPaddingRight = parseInt( labelStyle.paddingRight, 10 ); popover.style.position = 'fixed'; - popover.style.width = `${ anchorRect.width }px`; - popover.style.left = `${ left }px`; - popover.style.top = `${ top }px`; - - // Adjust position if popover goes off-screen - if ( top < 0 ) { - // If there's not enough space above, position it below the anchor - popover.style.top = `${ anchorRect.bottom + offset }px`; - } + popover.style.right = `${ + window.innerWidth - ( labelRect.right - labelPaddingRight ) + }px`; + popover.style.top = `${ labelRect.top - 30 }px`; + popover.style.left = 'auto'; setIsPositioned( true ); }, [ anchor ] ); @@ -128,6 +116,12 @@ export const LogoPopover: React.FC< LogoPopoverProps > = ( { zIndex: 1000, opacity: isPositioned ? 1 : 0, transition: 'opacity 0.2s', + gridTemplateColumns: `repeat(${ + React.Children.count( children ) > 5 + ? 5 + : React.Children.count( children ) + }, 38px)`, + left: 'auto', } } role="dialog" aria-label="Supported Credit Card Brands" diff --git a/client/checkout/blocks/payment-methods-logos/style.scss b/client/checkout/blocks/payment-methods-logos/style.scss index b5f08d2ef8d..4c7f113427a 100644 --- a/client/checkout/blocks/payment-methods-logos/style.scss +++ b/client/checkout/blocks/payment-methods-logos/style.scss @@ -29,19 +29,18 @@ background-color: #fff; border: 1px solid $gray-300; border-radius: 3px; - padding: 10px; + padding: 8px; box-sizing: border-box; box-shadow: 0 0 10px 0 rgba( 0, 0, 0, 0.1 ); display: grid; - grid-template-columns: repeat( auto-fit, minmax( 38px, 1fr ) ); - gap: 10px; - justify-items: center; - align-items: center; + gap: 8px; + justify-content: center; cursor: pointer; + width: fit-content; > img { + width: 38px; + height: 24px; box-shadow: 0 0 0 1px rgba( 0, 0, 0, 0.1 ); - max-width: 100%; - height: auto; } } diff --git a/client/checkout/classic/event-handlers.js b/client/checkout/classic/event-handlers.js index c866524f974..ac6179b9295 100644 --- a/client/checkout/classic/event-handlers.js +++ b/client/checkout/classic/event-handlers.js @@ -271,7 +271,19 @@ jQuery( function ( $ ) { ]; function getMaxElements() { - return window.innerWidth <= 330 ? 2 : 4; + const paymentMethodElement = document.querySelector( + '.payment_method_woocommerce_payments' + ); + if ( ! paymentMethodElement ) { + return 4; // Default fallback + } + + const elementWidth = paymentMethodElement.offsetWidth; + if ( elementWidth <= 300 ) { + return 1; + } else if ( elementWidth <= 330 ) { + return 2; + } } function shouldHavePopover() { @@ -296,6 +308,16 @@ jQuery( function ( $ ) { popover.appendChild( img ); } ); + // Calculate number of items per row (max 5) + const itemsPerRow = Math.min( remainingMethods.length, 5 ); + + // Set grid-template-columns based on number of items + popover.style.gridTemplateColumns = `repeat(${ itemsPerRow }, 38px)`; + + // Calculate width: (items * width) + (gaps * gap-size) + (padding * 2) + const width = itemsPerRow * 38 + ( itemsPerRow - 1 ) * 8 + 16; + popover.style.width = `${ width }px`; + return popover; } @@ -304,31 +326,16 @@ jQuery( function ( $ ) { if ( ! label ) return; const labelRect = label.getBoundingClientRect(); - const anchorRect = anchor.getBoundingClientRect(); - - if ( ! popover.dataset.labelOffset ) { - popover.style.visibility = 'hidden'; - popover.style.display = 'block'; - const popoverRect = popover.getBoundingClientRect(); - popover.style.display = ''; - popover.style.visibility = ''; - - const offset = 7; - const initialTop = labelRect.top - popoverRect.height - offset; - - // Store the offset from the label - popover.dataset.labelOffset = ( - labelRect.top - initialTop - ).toString(); - } - - const labelOffset = parseFloat( popover.dataset.labelOffset ); + const labelStyle = window.getComputedStyle( label ); + const labelPaddingRight = parseInt( labelStyle.paddingRight, 10 ); popover.style.position = 'fixed'; - popover.style.width = `${ anchorRect.width }px`; - popover.style.left = `${ anchorRect.left }px`; // Use anchor's left position - popover.style.top = `${ labelRect.top - labelOffset }px`; + popover.style.right = `${ + window.innerWidth - ( labelRect.right - labelPaddingRight ) + }px`; + popover.style.top = `${ labelRect.top - 25 }px`; popover.style.zIndex = '1000'; + popover.style.left = 'auto'; } function updateLogos() { @@ -352,6 +359,14 @@ jQuery( function ( $ ) { const countDiv = document.createElement( 'div' ); countDiv.className = 'payment-methods--logos-count'; countDiv.textContent = `+ ${ remainingCount }`; + + // Add click handler directly to the count div + countDiv.addEventListener( 'click', ( e ) => { + e.stopPropagation(); + e.preventDefault(); + togglePopover(); + } ); + innerContainer.appendChild( countDiv ); } @@ -424,13 +439,12 @@ jQuery( function ( $ ) { setupPopover(); } - // Click handler - innerContainer.addEventListener( 'click', togglePopover ); - - // Keyboard handler + // Remove the click handler from innerContainer since we're handling it on the count div + // Keep the keyboard handler for accessibility innerContainer.addEventListener( 'keydown', ( e ) => { if ( e.key === 'Enter' || e.key === ' ' ) { e.preventDefault(); + e.stopPropagation(); togglePopover(); } } ); diff --git a/client/checkout/classic/style.scss b/client/checkout/classic/style.scss index 2b937fb2dae..7d515babe6c 100644 --- a/client/checkout/classic/style.scss +++ b/client/checkout/classic/style.scss @@ -49,6 +49,24 @@ height: 24px !important; max-height: 24px !important; } + .logo-popover { + background-color: #fff; + border: 1px solid $gray-300; + border-radius: 3px; + padding: 8px; + box-sizing: border-box; + box-shadow: 0 0 10px 0 rgba( 0, 0, 0, 0.1 ); + display: grid; + gap: 8px; + justify-content: center; + cursor: pointer; + + > img { + box-shadow: 0 0 0 1px rgba( 0, 0, 0, 0.1 ); + width: 38px; + height: 24px; + } + } } }