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

Use the Button block inside of the Search block #39463

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,15 @@ function selectionHelper( state = {}, action ) {
* @return {boolean} Updated state.
*/
export function selection( state = {}, action ) {
if (
action.clientId ===
document.querySelector( '.wp-block-button' )?.dataset?.block
) {
action.clientId = document.querySelector(
Copy link
Contributor

Choose a reason for hiding this comment

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

This really looks like a hack 😁 and not sure if there even is a proper implementation of this.

'.wp-block-search'
)?.dataset?.block;
}

switch ( action.type ) {
case 'SELECTION_CHANGE':
return {
Expand Down
120 changes: 62 additions & 58 deletions packages/block-library/src/search/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import {
__experimentalUnitControl as UnitControl,
__experimentalUseColorProps as useColorProps,
store as blockEditorStore,
useInnerBlocksProps,
} from '@wordpress/block-editor';
import { useDispatch, useSelect } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import { useEffect, useMemo } from '@wordpress/element';
import {
ToolbarDropdownMenu,
ToolbarGroup,
Expand All @@ -32,7 +33,6 @@ import {
import { useInstanceId } from '@wordpress/compose';
import { Icon, search } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';

/**
* Internal dependencies
Expand All @@ -51,6 +51,7 @@ import {
MIN_WIDTH,
MIN_WIDTH_UNIT,
} from './utils.js';
import { cloneBlock } from '@wordpress/blocks';

// Used to calculate border radius adjustment to avoid "fat" corners when
// button is placed inside wrapper.
Expand All @@ -71,7 +72,6 @@ export default function SearchEdit( {
width,
widthUnit,
align,
buttonText,
buttonPosition,
buttonUseIcon,
style,
Expand All @@ -89,9 +89,10 @@ export default function SearchEdit( {
},
[ clientId ]
);
const { __unstableMarkNextChangeAsNotPersistent } = useDispatch(
blockEditorStore
);
const {
__unstableMarkNextChangeAsNotPersistent,
replaceInnerBlocks,
} = useDispatch( blockEditorStore );
useEffect( () => {
if ( ! insertedInNavigationBlock ) return;
// This side-effect should not create an undo level.
Expand Down Expand Up @@ -236,54 +237,62 @@ export default function SearchEdit( {
);
};

const renderButton = () => {
// If the button is inside the wrapper, the wrapper gets the border color styles/classes, not the button.
const buttonClasses = classnames(
'wp-block-search__button',
colorProps.className,
isButtonPositionInside ? undefined : borderProps.className,
buttonUseIcon ? 'has-icon' : undefined
);
const buttonStyles = {
...colorProps.style,
...( isButtonPositionInside
? { borderRadius }
: borderProps.style ),
};
const ALLOWED_BLOCKS = [ 'core/button' ];
const blockProps = useBlockProps( {
className: getBlockClassNames(),
} );

return (
<>
{ buttonUseIcon && (
<button
type="button"
className={ buttonClasses }
style={ buttonStyles }
aria-label={
buttonText
? stripHTML( buttonText )
: __( 'Search' )
}
>
<Icon icon={ search } />
</button>
) }
const { getBlocks } = useSelect( blockEditorStore );
const hasInnerBlocks = useSelect(
( select ) =>
select( blockEditorStore ).getBlocks( clientId ).length > 0,
[ clientId ]
);

{ ! buttonUseIcon && (
<RichText
className={ buttonClasses }
style={ buttonStyles }
aria-label={ __( 'Button text' ) }
placeholder={ __( 'Add button text…' ) }
withoutInteractiveFormatting
value={ buttonText }
onChange={ ( html ) =>
setAttributes( { buttonText: html } )
}
/>
) }
</>
// borderColor, style, backgroundColor, textColor, gradient
const getNextButtonAttrs = ( prevAttrs = {} ) => ( {
borderColor: isButtonPositionInside ? attributes.borderColor : {},
style: {
...attributes.style,
...( isButtonPositionInside ? { borderRadius } : {} ),
},
backgroundColor: attributes.backgroundColor,
textColor: attributes.textColor,
gradient: attributes.gradient,
// TODO: Use icon when needed
text: prevAttrs.text || 'Search',
} );

const template = useMemo(
() => [ [ 'core/button', getNextButtonAttrs() ] ],
[]
);
useEffect( () => {
const prevBlock = getBlocks( clientId )[ 0 ];
const nextBlock = cloneBlock(
prevBlock,
getNextButtonAttrs( prevBlock?.attributes ),
[]
);
};
replaceInnerBlocks( clientId, [ nextBlock ] );
}, [
isButtonPositionInside,
buttonUseIcon,
// Must serialize these two, they are new objects each time and
// keep triggering the effect
JSON.stringify( colorProps ),
Copy link
Contributor

Choose a reason for hiding this comment

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

This is weird :)

JSON.stringify( borderProps ),
hasInnerBlocks,
clientId,
] );

const innerBlocksProps = useInnerBlocksProps( blockProps, {
orientation: 'horizontal',
renderAppender: false,
template,
allowedBlocks: ALLOWED_BLOCKS,
} );
const button = <div { ...innerBlocksProps } />;

const controls = (
<>
Expand Down Expand Up @@ -439,10 +448,6 @@ export default function SearchEdit( {
return styles;
};

const blockProps = useBlockProps( {
className: getBlockClassNames(),
} );

return (
<div { ...blockProps }>
{ controls }
Expand All @@ -457,7 +462,6 @@ export default function SearchEdit( {
onChange={ ( html ) => setAttributes( { label: html } ) }
/>
) }

<ResizableBox
size={ {
width: `${ width }${ widthUnit }`,
Expand Down Expand Up @@ -487,11 +491,11 @@ export default function SearchEdit( {
{ ( isButtonPositionInside || isButtonPositionOutside ) && (
<>
{ renderTextField() }
{ renderButton() }
{ button }
</>
) }

{ hasOnlyButton && renderButton() }
{ hasOnlyButton && button }
{ hasNoButton && renderTextField() }
</ResizableBox>
</div>
Expand Down