From eb2454d07bfc98dfac00c10962e0e77e69a8b11b Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 14:00:43 +1000 Subject: [PATCH 1/9] Revert "Remove "Open in new window" link option (#4583)" This reverts commit 5ab37b76f2aebbc38a5c9d8ba5fa298ddf04e23e. --- blocks/rich-text/format-toolbar/index.js | 43 ++++++++++++++++++++-- blocks/rich-text/format-toolbar/style.scss | 18 ++++++++- blocks/rich-text/index.js | 4 +- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index 39b42751fdc211..ec0255007d2ded 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -12,6 +12,7 @@ import { keycodes } from '@wordpress/utils'; import './style.scss'; import UrlInput from '../../url-input'; import { filterURLForDisplay } from '../../../editor/utils/url'; +import ToggleControl from '../../inspector-controls/toggle-control'; const { ESCAPE, LEFT, RIGHT, UP, DOWN, BACKSPACE, ENTER } = keycodes; @@ -47,10 +48,11 @@ const stopKeyPropagation = ( event ) => event.stopPropagation(); class FormatToolbar extends Component { constructor() { super( ...arguments ); - this.state = { isAddingLink: false, isEditingLink: false, + settingsVisible: false, + opensInNewWindow: false, newLinkValue: '', }; @@ -60,6 +62,8 @@ class FormatToolbar extends Component { this.submitLink = this.submitLink.bind( this ); this.onKeyDown = this.onKeyDown.bind( this ); this.onChangeLinkValue = this.onChangeLinkValue.bind( this ); + this.toggleLinkSettingsVisibility = this.toggleLinkSettingsVisibility.bind( this ); + this.setLinkTarget = this.setLinkTarget.bind( this ); } onKeyDown( event ) { @@ -79,6 +83,8 @@ class FormatToolbar extends Component { this.setState( { isAddingLink: false, isEditingLink: false, + settingsVisible: false, + opensInNewWindow: !! nextProps.formats.link && !! nextProps.formats.link.target, newLinkValue: '', } ); } @@ -96,6 +102,16 @@ class FormatToolbar extends Component { }; } + toggleLinkSettingsVisibility() { + this.setState( ( state ) => ( { settingsVisible: ! state.settingsVisible } ) ); + } + + setLinkTarget( event ) { + const opensInNewWindow = event.target.checked; + this.setState( { opensInNewWindow } ); + this.props.onChange( { link: { value: this.props.formats.link.value, target: opensInNewWindow ? '_blank' : '' } } ); + } + addLink() { this.setState( { isEditingLink: false, isAddingLink: true, newLinkValue: '' } ); } @@ -112,7 +128,7 @@ class FormatToolbar extends Component { submitLink( event ) { event.preventDefault(); - this.props.onChange( { link: { value: this.state.newLinkValue } } ); + this.props.onChange( { link: { value: this.state.newLinkValue, target: this.state.opensInNewWindow ? '_blank' : '' } } ); if ( this.state.isAddingLink ) { this.props.speak( __( 'Link added.' ), 'assertive' ); } @@ -124,7 +140,7 @@ class FormatToolbar extends Component { render() { const { formats, focusPosition, enabledControls = DEFAULT_CONTROLS, customControls = [] } = this.props; - const { isAddingLink, isEditingLink, newLinkValue } = this.state; + const { isAddingLink, isEditingLink, newLinkValue, settingsVisible, opensInNewWindow } = this.state; const linkStyle = focusPosition ? { position: 'absolute', ...focusPosition } : null; @@ -140,6 +156,15 @@ class FormatToolbar extends Component { }; } ); + const linkSettings = settingsVisible && ( +
+ +
+ ); + return (
@@ -158,7 +183,13 @@ class FormatToolbar extends Component { +
+ { linkSettings } /* eslint-enable jsx-a11y/no-noninteractive-element-interactions */ @@ -183,7 +214,13 @@ class FormatToolbar extends Component { + + { linkSettings } /* eslint-enable jsx-a11y/no-static-element-interactions */ diff --git a/blocks/rich-text/format-toolbar/style.scss b/blocks/rich-text/format-toolbar/style.scss index a7403895d444a9..34bff958f18e8a 100644 --- a/blocks/rich-text/format-toolbar/style.scss +++ b/blocks/rich-text/format-toolbar/style.scss @@ -7,13 +7,17 @@ box-shadow: 0 3px 20px rgba( 18, 24, 30, .1 ), 0 1px 3px rgba( 18, 24, 30, .1 ); border: 1px solid #e0e5e9; background: #fff; - width: 300px; + width: 305px; display: flex; flex-direction: column; font-family: $default-font; font-size: $default-font-size; line-height: $default-line-height; z-index: z-index( '.blocks-format-toolbar__link-modal' ); + + .blocks-url-input { + width: auto; + } } .blocks-format-toolbar__link-modal-line { @@ -42,3 +46,15 @@ @include long-content-fade( $size: 40% ); } } + +.blocks-format-toolbar__link-settings { + padding: 7px 8px; + border-top: 1px solid $light-gray-500; + padding-top: 8px; // add 1px for the border + + .blocks-base-control { + margin: 0; + flex-grow: 1; + flex-shrink: 1; + } +} diff --git a/blocks/rich-text/index.js b/blocks/rich-text/index.js index 73f3eb2c45983b..d4528a6d37549c 100644 --- a/blocks/rich-text/index.js +++ b/blocks/rich-text/index.js @@ -103,7 +103,7 @@ export function getFormatProperties( formatName, parents ) { switch ( formatName ) { case 'link' : { const anchor = find( parents, node => node.nodeName.toLowerCase() === 'a' ); - return !! anchor ? { value: anchor.getAttribute( 'href' ) || '', node: anchor } : {}; + return !! anchor ? { value: anchor.getAttribute( 'href' ) || '', target: anchor.getAttribute( 'target' ) || '', node: anchor } : {}; } default: return {}; @@ -753,7 +753,7 @@ export class RichText extends Component { if ( ! anchor ) { this.removeFormat( 'link' ); } - this.applyFormat( 'link', { href: formatValue.value }, anchor ); + this.applyFormat( 'link', { href: formatValue.value, target: formatValue.target }, anchor ); } else { this.editor.execCommand( 'Unlink' ); } From f46cd447d255e869899fc92134fdafb17504a923 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 14:08:28 +1000 Subject: [PATCH 2/9] Fix 'Open in new window' link option Some changes had occured elsewhere in the codebase in between when this UI was reverted and when it was unreverted. - Imports `ToggleControl` correctly - Fixes `RichText` tests --- blocks/rich-text/format-toolbar/index.js | 12 ++++++++---- blocks/rich-text/format-toolbar/style.scss | 2 +- blocks/rich-text/test/index.js | 7 +++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index ec0255007d2ded..eca6d67bccb731 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -3,7 +3,13 @@ */ import { __ } from '@wordpress/i18n'; import { Component } from '@wordpress/element'; -import { IconButton, Toolbar, withSpokenMessages, Fill } from '@wordpress/components'; +import { + Fill, + IconButton, + ToggleControl, + Toolbar, + withSpokenMessages, +} from '@wordpress/components'; import { keycodes } from '@wordpress/utils'; /** @@ -12,7 +18,6 @@ import { keycodes } from '@wordpress/utils'; import './style.scss'; import UrlInput from '../../url-input'; import { filterURLForDisplay } from '../../../editor/utils/url'; -import ToggleControl from '../../inspector-controls/toggle-control'; const { ESCAPE, LEFT, RIGHT, UP, DOWN, BACKSPACE, ENTER } = keycodes; @@ -106,8 +111,7 @@ class FormatToolbar extends Component { this.setState( ( state ) => ( { settingsVisible: ! state.settingsVisible } ) ); } - setLinkTarget( event ) { - const opensInNewWindow = event.target.checked; + setLinkTarget( opensInNewWindow ) { this.setState( { opensInNewWindow } ); this.props.onChange( { link: { value: this.props.formats.link.value, target: opensInNewWindow ? '_blank' : '' } } ); } diff --git a/blocks/rich-text/format-toolbar/style.scss b/blocks/rich-text/format-toolbar/style.scss index 34bff958f18e8a..37fb7ed16df6ab 100644 --- a/blocks/rich-text/format-toolbar/style.scss +++ b/blocks/rich-text/format-toolbar/style.scss @@ -52,7 +52,7 @@ border-top: 1px solid $light-gray-500; padding-top: 8px; // add 1px for the border - .blocks-base-control { + .components-base-control { margin: 0; flex-grow: 1; flex-shrink: 1; diff --git a/blocks/rich-text/test/index.js b/blocks/rich-text/test/index.js index ea9f70d88444cf..f1fe726cf973ab 100644 --- a/blocks/rich-text/test/index.js +++ b/blocks/rich-text/test/index.js @@ -145,6 +145,7 @@ describe( 'getFormatProperties', () => { nodeName: 'A', attributes: { href: 'https://www.testing.com', + target: '_blank', }, }; @@ -156,7 +157,7 @@ describe( 'getFormatProperties', () => { expect( getFormatProperties( formatName, [ { ...node, nodeName: 'P' } ] ) ).toEqual( {} ); } ); - test( 'should return an object of value and node for a link', () => { + test( 'should return a populated object', () => { const mockNode = { ...node, getAttribute: jest.fn().mockImplementation( ( attr ) => mockNode.attributes[ attr ] ), @@ -168,11 +169,12 @@ describe( 'getFormatProperties', () => { expect( getFormatProperties( formatName, parents ) ).toEqual( { value: 'https://www.testing.com', + target: '_blank', node: mockNode, } ); } ); - test( 'should return an object of value and node of empty values when no values are found.', () => { + test( 'should return an object with empty values when no link is found', () => { const mockNode = { ...node, attributes: {}, @@ -185,6 +187,7 @@ describe( 'getFormatProperties', () => { expect( getFormatProperties( formatName, parents ) ).toEqual( { value: '', + target: '', node: mockNode, } ); } ); From b12be5b7b81290f4d1ecd4c5433f5de11bf97c5c Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 14:22:41 +1000 Subject: [PATCH 3/9] Use ellipsis icon for opening link settings Change the icon to be the same icon used elsewhere in the editor, and move the toggle button to the left of the link UI. --- blocks/rich-text/format-toolbar/index.js | 24 +++++++++++++--------- blocks/rich-text/format-toolbar/style.scss | 4 ++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index eca6d67bccb731..9ee71bd6d16a36 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -184,14 +184,16 @@ class FormatToolbar extends Component { onKeyDown={ this.onKeyDown } onSubmit={ this.submitLink }>
- - - + aria-expanded={ settingsVisible } + /> + + +
{ linkSettings } @@ -209,6 +211,13 @@ class FormatToolbar extends Component { onKeyPress={ stopKeyPropagation } >
+ -
{ linkSettings } diff --git a/blocks/rich-text/format-toolbar/style.scss b/blocks/rich-text/format-toolbar/style.scss index 37fb7ed16df6ab..f5af241dc23213 100644 --- a/blocks/rich-text/format-toolbar/style.scss +++ b/blocks/rich-text/format-toolbar/style.scss @@ -33,6 +33,10 @@ } } +.blocks-format-toolbar__link-settings-toggle .dashicon { + transform: rotate(90deg); +} + .blocks-format-toolbar__link-value { margin: 10px; flex-grow: 1; From 5f916d7e306c87a88a414d5bfbf3f1e11e85607b Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 14:50:37 +1000 Subject: [PATCH 4/9] Use link toolbar button to remove links Consolidate the dedicated 'remove link' button into the toolbar button that adds a link. --- blocks/rich-text/format-toolbar/index.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index 9ee71bd6d16a36..9d95d01b60ceb0 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -38,8 +38,6 @@ const FORMATTING_CONTROLS = [ format: 'strikethrough', }, { - icon: 'admin-links', - title: __( 'Link' ), format: 'link', }, ]; @@ -152,11 +150,22 @@ class FormatToolbar extends Component { const toolbarControls = FORMATTING_CONTROLS.concat( customControls ) .filter( control => enabledControls.indexOf( control.format ) !== -1 ) .map( ( control ) => { - const isLink = control.format === 'link'; + if ( control.format === 'link' ) { + const isFormatActive = this.isFormatActive( 'link' ); + const isActive = isFormatActive || isAddingLink; + return { + ...control, + icon: isFormatActive ? 'editor-unlink' : 'admin-links', // TODO: Need proper unlink icon + title: isFormatActive ? __( 'Unlink' ) : __( 'Link' ), + onClick: isActive ? this.dropLink : this.addLink, + isActive, + }; + } + return { ...control, - onClick: isLink ? this.addLink : this.toggleFormat( control.format ), - isActive: this.isFormatActive( control.format ) || ( isLink && isAddingLink ), + onClick: this.toggleFormat( control.format ), + isActive: this.isFormatActive( control.format ), }; } ); @@ -193,7 +202,6 @@ class FormatToolbar extends Component { /> - { linkSettings } @@ -226,7 +234,6 @@ class FormatToolbar extends Component { { formats.link.value && filterURLForDisplay( decodeURI( formats.link.value ) ) } - { linkSettings } From 4a9ff7aa1587a4fe454ed200c9363c66f81c0e8f Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 15:15:09 +1000 Subject: [PATCH 5/9] After editing a link, exit editing mode Reset the link UI once the user has edited the link value. --- blocks/rich-text/format-toolbar/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index 9d95d01b60ceb0..3ac788b7bfef96 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -130,6 +130,7 @@ class FormatToolbar extends Component { submitLink( event ) { event.preventDefault(); + this.setState( { isEditingLink: false, isAddingLink: false, newLinkValue: '' } ); this.props.onChange( { link: { value: this.state.newLinkValue, target: this.state.opensInNewWindow ? '_blank' : '' } } ); if ( this.state.isAddingLink ) { this.props.speak( __( 'Link added.' ), 'assertive' ); From d1110474b739e43e7e24974a15431485387fcbf3 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 15:16:08 +1000 Subject: [PATCH 6/9] Fix error when setting 'Open in new window' on a new link Don't call `onChange()` when 'Open in new window' is toggled if we are adding a new link (as opposed to editing an existing link). --- blocks/rich-text/format-toolbar/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index 3ac788b7bfef96..e195a070a275ba 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -111,7 +111,9 @@ class FormatToolbar extends Component { setLinkTarget( opensInNewWindow ) { this.setState( { opensInNewWindow } ); - this.props.onChange( { link: { value: this.props.formats.link.value, target: opensInNewWindow ? '_blank' : '' } } ); + if ( this.props.formats.link ) { + this.props.onChange( { link: { value: this.props.formats.link.value, target: opensInNewWindow ? '_blank' : '' } } ); + } } addLink() { From 8e64f3354ed99afcd960ad178f034ef7b2ef8057 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 15:45:32 +1000 Subject: [PATCH 7/9] Expand link UI to fit contents The link popup should widen to fit the URL within it. --- blocks/rich-text/format-toolbar/index.js | 111 ++++++++++----------- blocks/rich-text/format-toolbar/style.scss | 14 ++- blocks/rich-text/index.js | 3 +- 3 files changed, 61 insertions(+), 67 deletions(-) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index e195a070a275ba..07627a9ddb1eaf 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -146,9 +146,6 @@ class FormatToolbar extends Component { render() { const { formats, focusPosition, enabledControls = DEFAULT_CONTROLS, customControls = [] } = this.props; const { isAddingLink, isEditingLink, newLinkValue, settingsVisible, opensInNewWindow } = this.state; - const linkStyle = focusPosition ? - { position: 'absolute', ...focusPosition } : - null; const toolbarControls = FORMATTING_CONTROLS.concat( customControls ) .filter( control => enabledControls.indexOf( control.format ) !== -1 ) @@ -185,64 +182,64 @@ class FormatToolbar extends Component {
- { ( isAddingLink || isEditingLink ) && - // Disable reason: KeyPress must be suppressed so the block doesn't hide the toolbar - /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ + { ( isAddingLink || isEditingLink || formats.link ) && ( -
-
- - - -
- { linkSettings } -
-
- /* eslint-enable jsx-a11y/no-noninteractive-element-interactions */ - } - - { !! formats.link && ! isAddingLink && ! isEditingLink && - // Disable reason: KeyPress must be suppressed so the block doesn't hide the toolbar - /* eslint-disable jsx-a11y/no-static-element-interactions */ - -
- + /* eslint-enable jsx-a11y/no-static-element-interactions */ + ) }
- /* eslint-enable jsx-a11y/no-static-element-interactions */ - } + ) }
); } diff --git a/blocks/rich-text/format-toolbar/style.scss b/blocks/rich-text/format-toolbar/style.scss index f5af241dc23213..816ad1083f3990 100644 --- a/blocks/rich-text/format-toolbar/style.scss +++ b/blocks/rich-text/format-toolbar/style.scss @@ -3,11 +3,11 @@ } .blocks-format-toolbar__link-modal { - position: absolute; + position: relative; + left: -50%; box-shadow: 0 3px 20px rgba( 18, 24, 30, .1 ), 0 1px 3px rgba( 18, 24, 30, .1 ); border: 1px solid #e0e5e9; background: #fff; - width: 305px; display: flex; flex-direction: column; font-family: $default-font; @@ -16,7 +16,7 @@ z-index: z-index( '.blocks-format-toolbar__link-modal' ); .blocks-url-input { - width: auto; + width: 230px; } } @@ -42,13 +42,11 @@ flex-grow: 1; flex-shrink: 1; overflow: hidden; + text-overflow: ellipsis; position: relative; white-space: nowrap; - min-width: 0; - - &:after { - @include long-content-fade( $size: 40% ); - } + min-width: 150px; + max-width: 500px; } .blocks-format-toolbar__link-settings { diff --git a/blocks/rich-text/index.js b/blocks/rich-text/index.js index d4528a6d37549c..ba308587885283 100644 --- a/blocks/rich-text/index.js +++ b/blocks/rich-text/index.js @@ -432,11 +432,10 @@ export class RichText extends Component { const container = findRelativeParent( this.editor.getBody() ); const containerPosition = container.getBoundingClientRect(); const toolbarOffset = { top: 10, left: 0 }; - const linkModalWidth = 298; return { top: position.top - containerPosition.top + ( position.height ) + toolbarOffset.top, - left: position.left - containerPosition.left - ( linkModalWidth / 2 ) + ( position.width / 2 ) + toolbarOffset.left, + left: position.left - containerPosition.left + ( position.width / 2 ) + toolbarOffset.left, }; } From 94ab32613c3bb239154241aab9c75194837113f7 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 6 Apr 2018 16:34:27 +1000 Subject: [PATCH 8/9] Improve suggested links UI in link inserter Make the suggested links UI more stylistically consistent with the rest of the editor. --- blocks/rich-text/format-toolbar/style.scss | 34 ++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/blocks/rich-text/format-toolbar/style.scss b/blocks/rich-text/format-toolbar/style.scss index 816ad1083f3990..d2563986647760 100644 --- a/blocks/rich-text/format-toolbar/style.scss +++ b/blocks/rich-text/format-toolbar/style.scss @@ -14,22 +14,46 @@ font-size: $default-font-size; line-height: $default-line-height; z-index: z-index( '.blocks-format-toolbar__link-modal' ); - - .blocks-url-input { - width: 230px; - } } .blocks-format-toolbar__link-modal-line { + $button-size: 36px; + $input-padding: 10px; + $input-size: 230px; + display: flex; flex-direction: row; flex-grow: 1; flex-shrink: 1; min-width: 0; - align-items: center; + align-items: flex-start; .components-button { flex-shrink: 0; + width: $button-size; + height: $button-size; + } + + .blocks-url-input { + width: $input-size; + + input { + padding: $input-padding; + } + } + + .blocks-url-input__suggestions { + border-top: 1px solid $light-gray-500; + box-shadow: none; + left: -( $button-size ); + padding: 4px 0; + position: relative; + width: $input-size + $button-size * 2; + } + + .blocks-url-input__suggestion { + color: $dark-gray-100; + padding: 4px ( $button-size + $input-padding ); } } From 0bb6c854d92a78ddb3b1d7a52f3a7493f1f5600c Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Mon, 9 Apr 2018 11:37:42 +1000 Subject: [PATCH 9/9] Move settings button to right of the link UI Move the ellipsis button to the right of the edit button. This is more consistent with where the ellipsis icon is used elsewhere in the editor. --- blocks/rich-text/format-toolbar/index.js | 18 +++++++++--------- blocks/rich-text/format-toolbar/style.scss | 1 - 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/blocks/rich-text/format-toolbar/index.js b/blocks/rich-text/format-toolbar/index.js index 07627a9ddb1eaf..e7594faa545529 100644 --- a/blocks/rich-text/format-toolbar/index.js +++ b/blocks/rich-text/format-toolbar/index.js @@ -194,6 +194,8 @@ class FormatToolbar extends Component { onKeyDown={ this.onKeyDown } onSubmit={ this.submitLink }>
+ + - -
{ linkSettings } @@ -217,13 +217,6 @@ class FormatToolbar extends Component { onKeyPress={ stopKeyPropagation } >
- +
{ linkSettings } diff --git a/blocks/rich-text/format-toolbar/style.scss b/blocks/rich-text/format-toolbar/style.scss index d2563986647760..bb406bfe56f2a6 100644 --- a/blocks/rich-text/format-toolbar/style.scss +++ b/blocks/rich-text/format-toolbar/style.scss @@ -45,7 +45,6 @@ .blocks-url-input__suggestions { border-top: 1px solid $light-gray-500; box-shadow: none; - left: -( $button-size ); padding: 4px 0; position: relative; width: $input-size + $button-size * 2;