diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index 88562b719802b..39035bd1e9d4c 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -223,8 +223,14 @@ class URLInput extends Component { this.inputRef.current.focus(); } + static getDerivedStateFromProps( { showSuggestionsOverride }, { showSuggestions } ) { + return { + showSuggestions: showSuggestionsOverride !== undefined ? showSuggestionsOverride : showSuggestions, + }; + } + render() { - const { value = '', autoFocus = true, instanceId, className } = this.props; + const { value = '', autoFocus = true, instanceId, className, id, isFullWidth, hasBorder } = this.props; const { showSuggestions, suggestions, selectedSuggestion, loading } = this.state; const suggestionsListboxId = `block-editor-url-input-suggestions-${ instanceId }`; @@ -232,8 +238,12 @@ class URLInput extends Component { /* eslint-disable jsx-a11y/no-autofocus */ return ( -
+
} { showSuggestions && !! suggestions.length && - +
{ return omit( { @@ -37,6 +41,67 @@ const blockAttributes = { }; const deprecated = [ + { + attributes: { + ...blockAttributes, + align: { + type: 'string', + default: 'none', + }, + backgroundColor: { + type: 'string', + }, + textColor: { + type: 'string', + }, + customBackgroundColor: { + type: 'string', + }, + customTextColor: { + type: 'string', + }, + }, + save( { attributes } ) { + const { + url, + text, + title, + backgroundColor, + textColor, + customBackgroundColor, + customTextColor, + } = attributes; + + const textClass = getColorClassName( 'color', textColor ); + const backgroundClass = getColorClassName( 'background-color', backgroundColor ); + + const buttonClasses = classnames( 'wp-block-button__link', { + 'has-text-color': textColor || customTextColor, + [ textClass ]: textClass, + 'has-background': backgroundColor || customBackgroundColor, + [ backgroundClass ]: backgroundClass, + } ); + + const buttonStyle = { + backgroundColor: backgroundClass ? undefined : customBackgroundColor, + color: textClass ? undefined : customTextColor, + }; + + return ( +
+ +
+ ); + }, + migrate: colorsMigration, + }, { attributes: { ...blockAttributes, diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js index 142f9b0a06835..f4d38282c196c 100644 --- a/packages/block-library/src/button/edit.js +++ b/packages/block-library/src/button/edit.js @@ -7,12 +7,19 @@ import classnames from 'classnames'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { Component } from '@wordpress/element'; -import { compose } from '@wordpress/compose'; import { - Dashicon, - IconButton, + Component, +} from '@wordpress/element'; +import { + compose, + withInstanceId, +} from '@wordpress/compose'; +import { withFallbackStyles, + PanelBody, + TextControl, + ToggleControl, + BaseControl, } from '@wordpress/components'; import { URLInput, @@ -37,11 +44,15 @@ const applyFallbackStyles = withFallbackStyles( ( node, ownProps ) => { }; } ); +const NEW_TAB_REL = 'noreferrer noopener'; + class ButtonEdit extends Component { constructor() { super( ...arguments ); this.nodeRef = null; this.bindRef = this.bindRef.bind( this ); + this.onSetLinkRel = this.onSetLinkRel.bind( this ); + this.onToggleOpenInNewTab = this.onToggleOpenInNewTab.bind( this ); } bindRef( node ) { @@ -51,6 +62,27 @@ class ButtonEdit extends Component { this.nodeRef = node; } + onSetLinkRel( value ) { + this.props.setAttributes( { rel: value } ); + } + + onToggleOpenInNewTab( value ) { + const { rel } = this.props.attributes; + const linkTarget = value ? '_blank' : undefined; + + let updatedRel = rel; + if ( linkTarget && ! rel ) { + updatedRel = NEW_TAB_REL; + } else if ( ! linkTarget && rel === NEW_TAB_REL ) { + updatedRel = undefined; + } + + this.props.setAttributes( { + linkTarget, + rel: updatedRel, + } ); + } + render() { const { attributes, @@ -61,90 +93,108 @@ class ButtonEdit extends Component { fallbackBackgroundColor, fallbackTextColor, setAttributes, - isSelected, className, + instanceId, + isSelected, } = this.props; const { text, url, title, + linkTarget, + rel, } = attributes; + const linkId = `wp-block-button__inline-link-${ instanceId }`; + return ( - <> -
- setAttributes( { text: value } ) } - formattingControls={ [ 'bold', 'italic', 'strikethrough' ] } - className={ classnames( - 'wp-block-button__link', { - 'has-background': backgroundColor.color, - [ backgroundColor.class ]: backgroundColor.class, - 'has-text-color': textColor.color, - [ textColor.class ]: textColor.class, - } - ) } - style={ { - backgroundColor: backgroundColor.color, - color: textColor.color, - } } - keepPlaceholderOnFocus +
+ setAttributes( { text: value } ) } + formattingControls={ [ 'bold', 'italic', 'strikethrough' ] } + className={ classnames( + 'wp-block-button__link', { + 'has-background': backgroundColor.color, + [ backgroundColor.class ]: backgroundColor.class, + 'has-text-color': textColor.color, + [ textColor.class ]: textColor.class, + } + ) } + style={ { + backgroundColor: backgroundColor.color, + color: textColor.color, + } } + keepPlaceholderOnFocus + /> + + setAttributes( { url: value } ) } + showSuggestionsOverride={ ! isSelected ? false : undefined } + id={ linkId } + isFullWidth + hasBorder /> - - - - - -
- { isSelected && ( -
event.preventDefault() }> - - setAttributes( { url: value } ) } + + + + + + + + - - - ) } - + + +
); } } export default compose( [ + withInstanceId, withColors( 'backgroundColor', { textColor: 'color' } ), applyFallbackStyles, ] )( ButtonEdit ); diff --git a/packages/block-library/src/button/editor.scss b/packages/block-library/src/button/editor.scss index 6cfca2f62f080..4b0cc2381fb7d 100644 --- a/packages/block-library/src/button/editor.scss +++ b/packages/block-library/src/button/editor.scss @@ -70,52 +70,44 @@ text-overflow: ellipsis; } } -} - -.block-library-button__inline-link { - background: $white; - display: flex; - flex-wrap: wrap; - align-items: center; - font-family: $default-font; - font-size: $default-font-size; - line-height: $default-line-height; - // The width of input box plus padding plus two icon buttons. - $blocks-button__link-input-width: 300px + 2px + 2 * $icon-button-size; - width: $blocks-button__link-input-width; + // Limit width of the text field if empty + .wp-block-button__link[data-is-placeholder-visible="true"] { + max-width: 150px; + } +} - // Move it down by 2px so that it doesn't overlap the button focus outline. - margin-top: 2px; +.wp-block-button__inline-link { + color: $dark-gray-500; + height: 0; + overflow: hidden; + max-width: 290px; - .block-editor-url-input { - width: auto; + &-input__suggestions { + max-width: 290px; } - .block-editor-url-input__suggestions { - width: $blocks-button__link-input-width - $icon-button-size - $icon-button-size; - z-index: z-index(".block-library-button__inline-link .block-editor-url-input__suggestions"); - } + @media (min-width: #{ ($break-medium) }) { + max-width: 260px; - > .dashicon { - width: $icon-button-size; - } + &-input__suggestions { + max-width: 260px; + } - .dashicon { - color: $dark-gray-100; } + @media (min-width: #{ ($break-large) }) { + max-width: 290px; - .block-editor-url-input input[type="text"]::placeholder { - color: $dark-gray-100; - } + &-input__suggestions { + max-width: 290px; + } - [data-align="center"] & { - margin-left: auto; - margin-right: auto; } - [data-align="right"] & { - margin-left: auto; - margin-right: 0; + .is-selected &, + .is-typing & { + height: auto; + overflow: visible; + margin-top: $grid-size-large; } } diff --git a/packages/block-library/src/button/save.js b/packages/block-library/src/button/save.js index 67ce1225d2656..9b05e19b7b62f 100644 --- a/packages/block-library/src/button/save.js +++ b/packages/block-library/src/button/save.js @@ -20,6 +20,8 @@ export default function save( { attributes } ) { textColor, customBackgroundColor, customTextColor, + linkTarget, + rel, } = attributes; const textClass = getColorClassName( 'color', textColor ); @@ -46,6 +48,8 @@ export default function save( { attributes } ) { title={ title } style={ buttonStyle } value={ text } + target={ linkTarget } + rel={ rel } />
);