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

Position: Refactor "Position" controls panel to use ToolsPanel instead of PanelBody #67967

Merged
merged 8 commits into from
Jan 21, 2025

Conversation

yogeshbhutkar
Copy link
Contributor

@yogeshbhutkar yogeshbhutkar commented Dec 13, 2024

Fixes: #67950

What?

This PR introduces the usage of ToolsPanel instead of PanelBody inside the Position block support UI.

Why?

This PR is a part of #67813 which standardizes the usage of ToolsPanel inside Block Support UI.

How?

PanelBody is replaced with the corresponding ToolsPanel component.

Testing Instructions

  1. Insert a Group Block.
  2. Notice the presence of ToolsPanel component.
  3. Try to reset the updated values to test the reset functions.

Screencast

Screen.Recording.2024-12-13.at.4.03.43.PM.mov

@yogeshbhutkar yogeshbhutkar marked this pull request as ready for review December 13, 2024 10:48
Copy link

github-actions bot commented Dec 13, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: yogeshbhutkar <[email protected]>
Co-authored-by: fabiankaegy <[email protected]>
Co-authored-by: t-hamano <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@yogeshbhutkar yogeshbhutkar changed the title Refactor "Position" controls panel to use ToolsPanel instead of PanelBody Position: Refactor "Position" controls panel to use ToolsPanel instead of PanelBody Dec 13, 2024
@fabiankaegy fabiankaegy added [Type] Enhancement A suggestion for improvement. [Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi labels Dec 13, 2024
Copy link
Member

@fabiankaegy fabiankaegy left a comment

Choose a reason for hiding this comment

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

Before this update the position control also allowed you to update its value when multiple group blocks (blocks that support position) were selected. That code has been removed here.

For a single block this already works well. But we need to also handle multi block selection again :)

@yogeshbhutkar
Copy link
Contributor Author

yogeshbhutkar commented Dec 16, 2024

Before this update the position control also allowed you to update its value when multiple group blocks (blocks that support position) were selected. That code has been removed here.

For a single block this already works well. But we need to also handle multi block selection again :)

Before this update ( Trunk Branch ):

trunk_branch

After this update ( The current PR ):

this_pr

As demonstrated in the GIFs above, the position control indeed is capable of updating values when multiple group blocks are selected. It's also found to be working with 2 Group Blocks and 1 Row Block together.

Analysis of removed code:

const [ initialOpen, setInitialOpen ] = useState();

// Determine whether the panel should be expanded.
const { multiSelectedBlocks } = useSelect( ( select ) => {
  const { getBlocksByClientId, getSelectedBlockClientIds } =
	  select( blockEditorStore );
  const clientIds = getSelectedBlockClientIds();
  return {
	  multiSelectedBlocks: getBlocksByClientId( clientIds ),
  };
}, [] );

The above block is responsible to return the blocks that are currently selected.

useLayoutEffect( () => {
  // If any selected block has a position set, open the panel by default.
  // The first block's value will still be used within the control though.
  if ( initialOpen === undefined ) {
	  setInitialOpen(
		  multiSelectedBlocks.some(
			  ( { attributes } ) => !! attributes?.style?.position?.type
		  )
	  );
  }
}, [ initialOpen, multiSelectedBlocks, setInitialOpen ] );

This block of code toggles the state initialOpen if some of the blocks that are selected have position?.type. i.e., were assigned a position before.

This toggled state is used as an initial value for the initialOpen prop in the previous PanelBody component.

<PanelBody
	className="block-editor-block-inspector__position"
	title={ __( 'Position' ) }
	initialOpen={ initialOpen ?? false }
>
	<InspectorControls.Slot group="position" />
</PanelBody>

But, we don't need the initialOpen prop, hence, the above code is not required when using the ToolsPanel component, and hence was removed. As per my understanding, it has nothing to do with being able to update multiple selected blocks.

Please let me know if I'm missing out something in my approach, but as per the comment, @fabiankaegy mentioned the component now does not support updating position when multiple blocks are selected, but that doesn't seem to be the case and multi-block selection + updation, in my opinion is working properly as demonstrated in the 2nd GIF.

Can you please provide a screencast for my reference, if this doesn't answer the bug that you've mentioned?

CC: @fabiankaegy

@yogeshbhutkar
Copy link
Contributor Author

yogeshbhutkar commented Dec 18, 2024

Hi @fabiankaegy, circling back to check if the above comment resolves this review. Please let me know if any changes still need to be made.

@yogeshbhutkar
Copy link
Contributor Author

Hi @Mamaduka,
Could you please review this PR when you get a moment? This PR wasn't getting enough momentum and the issue stands unresolved.

@t-hamano t-hamano self-requested a review January 18, 2025 04:45
Copy link
Contributor

@t-hamano t-hamano left a comment

Choose a reason for hiding this comment

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

@yogeshbhutkar Thanks for the PR!

But, we don't need the initialOpen prop, hence, the above code is not required when using the ToolsPanel component, and hence was removed. As per my understanding, it has nothing to do with being able to update multiple selected blocks.

It is true that there is no initialOpen prop for ToolsPanel or ToolsPanelItem, but an equivalent prop might be the isShownByDefault prop of the ToolsPanelItem component.

For example, is it possible to use the isShowbByDefault prop conditionally, as shown below?

const PositionControlsPanel = () => {
	// ...

	// If any selected block has a position set, show the control by default.
	const isShownByDefault = useSelect( ( select ) => {
		const { getBlocksByClientId, getSelectedBlockClientIds } =
			select( blockEditorStore );
		const clientIds = getSelectedBlockClientIds();
		const multiSelectedBlocks = getBlocksByClientId( clientIds );
		return multiSelectedBlocks.some(
			( { attributes } ) => !! attributes?.style?.position?.type
		);
	}, [] );

	// ...

	return (
		<ToolsPanel>
			<ToolsPanelItem
				isShownByDefault={ isShownByDefault }
				label={ __( 'Position' ) }
			></ToolsPanelItem>
		</ToolsPanel>
	);
};

@yogeshbhutkar
Copy link
Contributor Author

yogeshbhutkar commented Jan 20, 2025

Thanks for the review @t-hamano, I've refactored the PR to accommodate the suggested changes.

Screen.Recording.2025-01-20.at.12.21.08.PM.mov

Comment on lines 43 to 49
updateBlockAttributes( selectedClientIDs, {
style: {
position: {
type: undefined,
},
},
} );
Copy link
Contributor

Choose a reason for hiding this comment

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

If a block has other styles, those styles will be reset unintentionally as well. I think all styles that are not related to position should be preserved. See this example.

Copy link
Contributor Author

@yogeshbhutkar yogeshbhutkar Jan 21, 2025

Choose a reason for hiding this comment

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

In the latest commit, I used the uniqueByBlock attribute and passed keyed clientIds with their attributes as the second parameter in updateBlockAttributes. This ensures the styles of the respective blocks are preserved when multiple blocks are reset.

However, I found this bug (within the existing implementation, not caused due to this PR):

Screen.Recording.2025-01-21.at.12.28.53.PM.mov

Setting the position to sticky when multiple blocks are selected applies the styles of the first block to all the other selected blocks overriding their applied styles.

I believe we should also update the onChangeType here:

const onChangeType = ( next ) => {

Updating it for all the selected blocks fixed the bug for me. Do I create a separate PR as this is a separate bug?

const onChangeType = ( next ) => {
  const placementValue = '0px';
  const attributesByClientId = Object.fromEntries(
	  selectedBlocks?.map(
		  ( { clientId: blockClientId, attributes } ) => [
			  blockClientId,
			  {
				  style: cleanEmptyObject( {
					  ...attributes?.style,
					  position: {
						  ...attributes?.style?.position,
						  type: next,
						  top:
							  next === 'sticky' || next === 'fixed'
								  ? placementValue
								  : undefined,
					  },
				  } ),
			  },
		  ]
	  )
  );
  updateBlockAttributes( selectedClientIds, attributesByClientId, true );
};

Also, there's already a resetPosition function exported here:

export function resetPosition( { attributes = {}, setAttributes } ) {

But, it accepts setAttributes, considering the above bug, I believe it's better to remove this implementation as it's not used anywhere in favor of the resetPosition in this PR.

CC: @t-hamano

Copy link
Contributor

@t-hamano t-hamano left a comment

Choose a reason for hiding this comment

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

LGTM!

However, I found this bug (within the existing implementation, not caused due to this PR):

Setting the position to sticky when multiple blocks are selected applies the styles of the first block to all the other selected blocks overriding their applied styles.

Good catch! This issue could be addressed in a follow-up.

@t-hamano t-hamano dismissed fabiankaegy’s stale review January 21, 2025 08:17

I believe the controls work correctly when multiple blocks are selected.

@t-hamano t-hamano merged commit 34f09ca into WordPress:trunk Jan 21, 2025
64 of 65 checks passed
@github-actions github-actions bot added this to the Gutenberg 20.2 milestone Jan 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Design Tools Tools that impact the appearance of blocks both to expand the number of tools and improve the experi [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor "Position" block support UI to use ToolsPanel instead of PanelBody
3 participants