diff --git a/packages/block-library/src/search/block.json b/packages/block-library/src/search/block.json index 0a2f217aca34b..92de1d6f028b3 100644 --- a/packages/block-library/src/search/block.json +++ b/packages/block-library/src/search/block.json @@ -5,16 +5,35 @@ "label": { "type": "string" }, + "showLabel": { + "type": "bool", + "default": true + }, "placeholder": { "type": "string", "default": "" }, + "width": { + "type": "number" + }, + "widthUnit": { + "type": "string" + }, "buttonText": { "type": "string" + }, + "buttonPosition": { + "type": "string", + "default": "button-outside" + }, + "buttonUseIcon": { + "type": "bool", + "default": false } }, "supports": { - "align": true, - "html": false + "align": [ "left", "center", "right" ], + "html": false, + "lightBlockWrapper": true } } diff --git a/packages/block-library/src/search/edit.js b/packages/block-library/src/search/edit.js index 5de591fb867ae..3665c8cdac047 100644 --- a/packages/block-library/src/search/edit.js +++ b/packages/block-library/src/search/edit.js @@ -1,22 +1,130 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ -import { RichText } from '@wordpress/block-editor'; +import { + __experimentalBlock as Block, + BlockControls, + InspectorControls, + RichText, + __experimentalUnitControl as UnitControl, +} from '@wordpress/block-editor'; +import { + DropdownMenu, + MenuGroup, + MenuItem, + ToolbarGroup, + Button, + ButtonGroup, + ToolbarButton, + ResizableBox, + PanelBody, + BaseControl, +} from '@wordpress/components'; +import { useInstanceId } from '@wordpress/compose'; +import { search } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; -export default function SearchEdit( { className, attributes, setAttributes } ) { - const { label, placeholder, buttonText } = attributes; +/** + * Internal dependencies + */ +import { + buttonOnly, + buttonOutside, + buttonInside, + noButton, + buttonWithIcon, + toggleLabel, +} from './icons'; - return ( -
- setAttributes( { label: html } ) } - /> +/** + * Constants + */ +const MIN_WIDTH = 220; +const MIN_WIDTH_UNIT = 'px'; +const PC_WIDTH_DEFAULT = 50; +const PX_WIDTH_DEFAULT = 350; +const CSS_UNITS = [ + { value: '%', label: '%', default: PC_WIDTH_DEFAULT }, + { value: 'px', label: 'px', default: PX_WIDTH_DEFAULT }, +]; + +export default function SearchEdit( { + className, + attributes, + setAttributes, + toggleSelection, + isSelected, +} ) { + const { + label, + showLabel, + placeholder, + width, + widthUnit, + align, + buttonText, + buttonPosition, + buttonUseIcon, + } = attributes; + + const unitControlInstanceId = useInstanceId( UnitControl ); + const unitControlInputId = `wp-block-search__width-${ unitControlInstanceId }`; + + const getBlockClassNames = () => { + return classnames( + className, + 'button-inside' === buttonPosition + ? 'wp-block-search__button-inside' + : undefined, + 'button-outside' === buttonPosition + ? 'wp-block-search__button-outside' + : undefined, + 'no-button' === buttonPosition + ? 'wp-block-search__no-button' + : undefined, + 'button-only' === buttonPosition + ? 'wp-block-search__button-only' + : undefined, + buttonUseIcon && 'no-button' !== buttonPosition + ? 'wp-block-search__text-button' + : undefined, + ! buttonUseIcon && 'no-button' !== buttonPosition + ? 'wp-block-search__icon-button' + : undefined + ); + }; + + const getButtonPositionIcon = () => { + switch ( buttonPosition ) { + case 'button-inside': + return buttonInside; + case 'button-outside': + return buttonOutside; + case 'no-button': + return noButton; + case 'button-only': + return buttonOnly; + } + }; + + const getResizableSides = () => { + if ( 'button-only' === buttonPosition ) { + return {}; + } + + return { + right: align === 'right' ? false : true, + left: align === 'right' ? true : false, + }; + }; + + const renderTextField = () => { + return ( - setAttributes( { buttonText: html } ) } - /> -
+ ); + }; + + const renderButton = () => { + return ( + <> + { buttonUseIcon && ( + + ); + } ) } + + + + + + ); + + return ( + + { controls } + + { showLabel && ( + setAttributes( { label: html } ) } + /> + ) } + + { + setAttributes( { + width: parseInt( elt.offsetWidth, 10 ), + widthUnit: 'px', + } ); + toggleSelection( false ); + } } + onResizeStop={ ( event, direction, elt, delta ) => { + setAttributes( { + width: parseInt( width + delta.width, 10 ), + } ); + toggleSelection( true ); + } } + showHandle={ isSelected } + > + { ( 'button-inside' === buttonPosition || + 'button-outside' === buttonPosition ) && ( + <> + { renderTextField() } + { renderButton() } + + ) } + + { 'button-only' === buttonPosition && renderButton() } + { 'no-button' === buttonPosition && renderTextField() } + + ); } diff --git a/packages/block-library/src/search/editor.scss b/packages/block-library/src/search/editor.scss index 1564fcedc3cda..bc2cd0dfe6e38 100644 --- a/packages/block-library/src/search/editor.scss +++ b/packages/block-library/src/search/editor.scss @@ -1,18 +1,27 @@ .wp-block-search { - &__input { + .wp-block-search__input { + padding: $grid-unit-10; + } + + &.wp-block-search__button-inside .wp-block-search__inside-wrapper { + padding: $grid-unit-05; + } + + .wp-block-search__input, + &.wp-block-search__button-inside .wp-block-search__inside-wrapper { border-radius: $radius-block-ui; border: 1px solid $dark-gray-200; color: $dark-gray-placeholder; font-family: $default-font; font-size: $default-font-size; - padding: $grid-unit-10; + background-color: $white; &:focus { outline: none; } } - &__button { + .wp-block-search__button { background: #f7f7f7; border-radius: $radius-block-ui; border: 1px solid #ccc; @@ -20,5 +29,10 @@ font-family: $default-font; font-size: $default-font-size; padding: 6px 10px; + color: $dark-gray-700; + } + + &__components-button-group { + margin-top: 10px; } } diff --git a/packages/block-library/src/search/icons.js b/packages/block-library/src/search/icons.js new file mode 100644 index 0000000000000..d795398382859 --- /dev/null +++ b/packages/block-library/src/search/icons.js @@ -0,0 +1,89 @@ +/** + * WordPress dependencies + */ +import { SVG, Rect } from '@wordpress/components'; + +export const buttonOnly = ( + + + +); + +export const buttonOutside = ( + + + + +); + +export const buttonInside = ( + + + + +); + +export const noButton = ( + + + +); + +export const buttonWithIcon = ( + + + + +); + +export const toggleLabel = ( + + + + +); diff --git a/packages/block-library/src/search/index.php b/packages/block-library/src/search/index.php index d1f7e84d2d915..08c8652839835 100644 --- a/packages/block-library/src/search/index.php +++ b/packages/block-library/src/search/index.php @@ -27,42 +27,79 @@ function render_block_core_search( $attributes ) { ) ); - $input_id = 'wp-block-search__input-' . ++$instance_id; - $label_markup = ''; - $button_markup = ''; + $input_id = 'wp-block-search__input-' . ++$instance_id; + $classnames = classnames_for_block_core_search( $attributes ); + $show_label = ( ! empty( $attributes['showLabel'] ) ) ? true : false; + $use_icon_button = ( ! empty( $attributes['buttonUseIcon'] ) ) ? true : false; + $show_input = ( ! empty( $attributes['buttonPosition'] ) && 'button-only' === $attributes['buttonPosition'] ) ? false : true; + $show_button = ( ! empty( $attributes['buttonPosition'] ) && 'no-button' === $attributes['buttonPosition'] ) ? false : true; + $label_markup = ''; + $input_markup = ''; + $button_markup = ''; + $width_styles = ''; - if ( ! empty( $attributes['label'] ) ) { - $label_markup = sprintf( - '', - $input_id, - $attributes['label'] - ); - } else { - $label_markup = sprintf( - '', + if ( $show_label ) { + if ( ! empty( $attributes['label'] ) ) { + $label_markup = sprintf( + '', + $input_id, + $attributes['label'] + ); + } else { + $label_markup = sprintf( + '', + $input_id, + __( 'Search' ) + ); + } + } + + if ( $show_input ) { + $input_markup = sprintf( + '', $input_id, - __( 'Search' ) + esc_attr( get_search_query() ), + esc_attr( $attributes['placeholder'] ) ); } - $input_markup = sprintf( - '', - $input_id, - esc_attr( get_search_query() ), - esc_attr( $attributes['placeholder'] ) - ); + if ( $show_button ) { + $button_internal_markup = ''; + + if ( ! $use_icon_button ) { + if ( ! empty( $attributes['buttonText'] ) ) { + $button_internal_markup = $attributes['buttonText']; + } + } else { + $button_internal_markup = + ' + + '; + } - if ( ! empty( $attributes['buttonText'] ) ) { $button_markup = sprintf( '', - $attributes['buttonText'] + $button_internal_markup ); } + if ( ! empty( $attributes['width'] ) && ! empty( $attributes['widthUnit'] ) ) { + if ( ! empty( $attributes['buttonPosition'] ) && 'button-only' !== $attributes['buttonPosition'] ) { + $width_styles = ' style="width: ' . $attributes['width'] . $attributes['widthUnit'] . ';"'; + } + } + + $field_markup = sprintf( + '
%s
', + $width_styles, + $input_markup . $button_markup + ); + return sprintf( - '
%s
', + '', esc_url( home_url( '/' ) ), - $label_markup . $input_markup . $button_markup + $classnames, + $label_markup . $field_markup ); } @@ -78,3 +115,44 @@ function register_block_core_search() { ); } add_action( 'init', 'register_block_core_search' ); + +/** + * Builds the correct top level classnames for the 'core/search' block. + * + * @param array $attributes The block attributes. + * + * @return string The classnames used in the block. + */ +function classnames_for_block_core_search( $attributes ) { + $classnames = array(); + + if ( ! empty( $attributes['buttonPosition'] ) ) { + if ( 'button-inside' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__button-inside'; + } + + if ( 'button-outside' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__button-outside'; + } + + if ( 'no-button' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__no-button'; + } + + if ( 'button-only' === $attributes['buttonPosition'] ) { + $classnames[] = 'wp-block-search__button-only'; + } + } + + if ( isset( $attributes['buttonUseIcon'] ) ) { + if ( ! empty( $attributes['buttonPosition'] ) && 'no-button' !== $attributes['buttonPosition'] ) { + if ( $attributes['buttonUseIcon'] ) { + $classnames[] = 'wp-block-search__icon-button'; + } else { + $classnames[] = 'wp-block-search__text-button'; + } + } + } + + return implode( ' ', $classnames ); +} diff --git a/packages/block-library/src/search/style.scss b/packages/block-library/src/search/style.scss index aaa4724ac3192..2c8b03cafb275 100644 --- a/packages/block-library/src/search/style.scss +++ b/packages/block-library/src/search/style.scss @@ -1,6 +1,10 @@ .wp-block-search { - display: flex; - flex-wrap: wrap; + .wp-block-search__inside-wrapper { + display: flex; + flex: auto; + flex-wrap: nowrap; + max-width: 100%; + } .wp-block-search__label { width: 100%; @@ -8,10 +12,43 @@ .wp-block-search__input { flex-grow: 1; - max-width: 22.5em; + min-width: 3em; + border: 1px solid $dark-gray-200; } .wp-block-search__button { margin-left: 0.625em; + word-break: normal; + + svg { + min-width: 1.5em; + min-height: 1.5em; + } + } + + &.wp-block-search__button-only { + .wp-block-search__button { + margin-left: 0; + } + } + + &.wp-block-search__button-inside .wp-block-search__inside-wrapper { + padding: $grid-unit-05; + border: 1px solid $dark-gray-200; + + .wp-block-search__input { + border-radius: 0; + border: none; + padding: 0 0 0 0.25em; + + &:focus { + outline: none; + } + } + + .wp-block-search__button { + padding: 0.125em 0.5em; + } } } + diff --git a/packages/e2e-tests/fixtures/blocks/core__search.json b/packages/e2e-tests/fixtures/blocks/core__search.json index e52d38cd79ca2..9bfe776f2127f 100644 --- a/packages/e2e-tests/fixtures/blocks/core__search.json +++ b/packages/e2e-tests/fixtures/blocks/core__search.json @@ -4,7 +4,10 @@ "name": "core/search", "isValid": true, "attributes": { - "placeholder": "" + "buttonPosition": "button-outside", + "buttonUseIcon": false, + "placeholder": "", + "showLabel": true }, "innerBlocks": [], "originalContent": "" diff --git a/packages/e2e-tests/fixtures/blocks/core__search__custom-text.json b/packages/e2e-tests/fixtures/blocks/core__search__custom-text.json index fb91161919c83..5d2c86a18d590 100644 --- a/packages/e2e-tests/fixtures/blocks/core__search__custom-text.json +++ b/packages/e2e-tests/fixtures/blocks/core__search__custom-text.json @@ -4,9 +4,12 @@ "name": "core/search", "isValid": true, "attributes": { + "buttonPosition": "button-outside", "label": "Custom label", "placeholder": "Custom placeholder", - "buttonText": "Custom button text" + "buttonText": "Custom button text", + "buttonUseIcon": false, + "showLabel": true }, "innerBlocks": [], "originalContent": ""