Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Product Collection: Migrate displayLayout To supports.layout #46255

Draft
wants to merge 9 commits into
base: trunk
Choose a base branch
from

Conversation

ObliviousHarmony
Copy link
Contributor

@ObliviousHarmony ObliviousHarmony commented Apr 4, 2024

Submission Review Guidelines:

Changes proposed in this Pull Request:

This pull request replaces the Product Collection block's custom displayLayout with Gutenberg's native layout block support. This allows us to take advantage of spacing support as well as the continued development of layout. This migration lets us avoid creating our own CSS styles and controls to handle editing margin, padding, and block spacing.

Closes #43307.

How to test the changes in this Pull Request:

Using the WooCommerce Testing Instructions Guide, include your detailed testing instructions:

  1. Create a Product Collection block and edit the layout on the collection block. Test it out!
  2. There are new controls for Margin, Padding, and Block Spacing on the collection and template blocks to try out.
  3. Create a Product Collection block on trunk:
    a. Confirm that the render callback works on this branch with an immigrated block.
    b. Confirm that the migration works and converts different configurations to the new attribute.

Changelog entry

  • Automatically create a changelog entry from the details below.

Significance

  • Patch
  • Minor
  • Major

Type

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement - Improvement to existing functionality

Message

Comment

@ObliviousHarmony ObliviousHarmony added the block: product collection Issues related to the Product Collection block label Apr 4, 2024
This is just a rough attempt at replacing the
displayLayout attribute in the editor. There is
no frontend support for it yet and I removed the
responsive grid. Once that's restored I can play
with the frontend.
@ObliviousHarmony ObliviousHarmony force-pushed the replace/replace-collection-display-layout branch from e3848e4 to 97ea00a Compare April 5, 2024 05:33
@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Apr 5, 2024
Copy link
Contributor

github-actions bot commented Apr 5, 2024

Hi @imanish003, @kmanijak,

Apart from reviewing the code changes, please make sure to review the testing instructions as well.

You can follow this guide to find out what good testing instructions should look like:
https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions

Copy link
Contributor

@imanish003 imanish003 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @ObliviousHarmony,

Thank you for your fantastic work on this PR. You've done an amazing job, and I really appreciate your effort in going the extra mile and implementing migration for existing blocks 🚀

I've left several minor suggestions. Most of them are nitpicks, so please feel free to ignore any you disagree with 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: When a new block is added to the post, the default COLUMN MODE is Manual. It would be better if we could change it to "Auto" because we want to keep the block responsive by default 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that currently the caveats to "Auto" warrant using "Manual" by default. As we figure out what responsiveness looks like with this layout option we can re-asses. How does that sound?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking in case I missed it earlier, but could you please clarify the specific caveat you're referring to?

If I recall correctly, we've had this discussion before and decided to make the block responsive by default. With that in mind, I believe we should aim to maintain responsiveness if possible. IMO, sticking with manual might not offer the best user experience across different device sizes.

CC: @kmanijak

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it stands, the supports.layout option only supports a static columnCount or a dynamic minimumColumnWidth. There is currently no way to combine these two into a minimum width with a maximum number of columns in the way that our custom layout does. I did find a workaround (the custom CSS in the migration) but want to get confirmation from Gutenberg before moving forward with that and getting responsiveness working again.

If Gutenberg indicates that the solution won't be supported long-term then we will need to decide whether or not to move forward with this migration. Ultimately, if they don't agree, the only "responsiveness" supported by Gutenberg in this case would be the minimumColumnWidth which has no maximum column count.

Think of this PR as a deeply researched PoC 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

want to get confirmation from Gutenberg before moving forward with that and getting responsiveness working again.

🙌🏻

Ultimately, if they don't agree, the only "responsiveness" supported by Gutenberg in this case would be the minimumColumnWidth which has no maximum column count.

If they don't agree! I believe we will need to discuss this with @jarekmorawski before making a decision 🙂

Think of this PR as a deeply researched PoC 😄

Yeah! I can see that. Well done! 😀🚀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we will need to discuss this with @jarekmorawski before making a decision

Yep! I'm just waiting to have some certainty around what that is or whether there is one to make!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When switching between Auto and Manual modes, there is a noticeable flickering in the UI, as captured video below. Is it possible to fix it? 🤔

Screen.Recording.2024-04-05.at.2.22.27.PM.mov

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I'm not sure what causes this! @kmanijak had an idea but that didn't seem to make a difference. For what it's worth, regarding Karol's comment, I don't think this ever caused unnecessary re-renders in the first place.

Do you have any ideas about what might be happening here? We're changing the control based on isAutoColumnLayout so it should be atomic but it isn't?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can fix it while addressing #46255 (comment) below. For example, refactoring the code as follows could potentially resolve the flickering issue:

<ToolsPanelItem
	label={ minimumColumnWidthLabel }
	hasValue={ () => true }
	isShownByDefault
>
	{ isAutoColumnLayout ? (
		<UnitControl
			label={ minimumColumnWidthLabel }
			value={ templateLayout.minimumColumnWidth as string }
			onChange={ onMinimumColumnWidthChange }
		/>
	) : (
		<RangeControl
			label={ columnCountLabel }
			onChange={ onColumnCountChange }
			value={ templateLayout.columnCount as number }
			min={ 2 }
			max={ 6 }
		/>
	) }
</ToolsPanelItem>

I haven't delved deeply into it, but my initial thought is that the flickering may result from the conditional rendering of the ToolsPanelItem component, particularly because it also needs to update the dropdown menu (see screenshot) whenever we render ToolsPanelItem. However, this is just an initial hypothesis; further investigation is needed to confirm.
image

Copy link
Contributor

@kmanijak kmanijak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work!

  1. We move to Gutenberg native solution
  2. As far I can see you were able to preserve all of the requirements in terms of which options are available where, right?

I played around with this and left some comments, some of them should be addressed before merging but overall, great work. 😆

There's one more thing you couldn't know about (especially because it's not covered with tests). There's migration from Products (Beta) to Product Collection block:

image

There's:

These mappings should be adjusted but at the same time, I think we may think about removing the option to migrate. I mean... options is available for months and as both blocks diverge more and more from each other I don't like us maintaining migration for too long. So I'll raise the discussion if and how long we want to preserve that option.

attributes: { displayLayout: DisplayLayoutAttribute },
innerBlocks: BlockInstance[]
) => {
const { displayLayout = null, ...newAttributes } = attributes;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const { displayLayout = null, ...newAttributes } = attributes;
const { displayLayout, ...newAttributes } = attributes;

Nitpick: Default value will be assigned only if displayLayout is undefined and that will be caught in line 23 anyway so I think it's simpler without defaulting to null.

Comment on lines 34 to 43
if ( shrinkColumns ) {
// We can replicate the previous responsive behavior with percentage
// based minimum width. One consideration, however, is that the
// block gap is not accounted for. We can approximate it by
// not using 90% as the width for our column area instead.
const columnWidth = Math.floor( 90 / columns );
templateLayout = {
type: LayoutOptions.GRID,
minimumColumnWidth: columnWidth + '%',
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a nice approximation! But the previous solution was based on specific minimum product width 150px (here) so I'd use DEFAULT_LAYOUT_GRID_MINIMUM_COLUMN_WIDTH here with no calculations.

columns were used as "max number of columns" so that's not a good source for the calculations as it results in wrong results for smaller screens.

When I tested the PR I encountered a case in which Product Collection was 3-column on trunk and 4-column on this branch. Setting the minimumColumnWidth to 150px in Inspector Controls allowed me to get the same result as on trunk.

Or am I missing something 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second thoughts. We're not able to migrate one logic to another, because:

  • old logic was based on maximum number of columns and minimum column width
  • new logic is based on minimum column width only (no upper limit).

So... Hmm... There's no right solution here 🙈 And I'm no longer convinced to my suggestion as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with 90% because it felt like a good approximation. At your prompting, however, I took a deeper look. We dealt with this in the old styles using this CSS:

$gap-count: calc(#{ $i } - 1);
$total-gap-width: calc(#{ $gap-count } * #{ $grid-gap });
$max-product-width: calc((100% - #{ $total-gap-width }) / #{ $i });

&.columns-#{ $i } {
  grid-template-columns: repeat(auto-fill, minmax(max(#{ $min-product-width }, #{ $max-product-width }), 1fr));
}

As we can see, it includes a calculation for the gap width and uses a percentage.

A caveat, however, is that we're now using a dynamic gap value through supports.spacing.blockGap. Even if we used this CSS class we wouldn't be able to replicate the previous responsive behavior!

Using the above calculation and the default blockGap value I will take another pass at having the percentage be identical.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again @kmanijak! I went back and adjusted the math. It should now work in every case, please test it out!

Assuming it works, I'll make some changes to the editor controls so that they look correct. As an aside, if we support block spacing, we can't support the kind of responsive layout we had before without writing our own block spacing and abandoning this migration altogether.

This was fine before because the block gap was hardcoded. With it being configurable like this, our CSS classes can't know the size and therefore can't do the necessary math.

</ToolsPanelItem>

{ autoColumns && (
<ToolsPanelItem
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
block: product collection Issues related to the Product Collection block plugin: woocommerce Issues related to the WooCommerce Core plugin.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Product Collection/Template block: Add Block Spacing
3 participants