gutenberg icon indicating copy to clipboard operation
gutenberg copied to clipboard

Remove "preview" mode/step from Link Control component

Open getdave opened this issue 1 year ago • 51 comments

What?

Removes the "Preview" UI state from the Link Control. This means it's always possible to directly edit a link without an extra "edit" click.

⚠️ There is a potential regression in this PR. See Backwards compatbility below.

Closes https://github.com/WordPress/gutenberg/issues/50892

Why?

As the control has evolved the preview step has become less and less useful. The main concerns are:

By removing the dedicated preview step we solve all these issues whilst improving the usability. The "preview" is still there but it is now alongside the edit state (albeit in a slimed down form).

How?

  • Removes all references to editing/preview mode.
  • Places the preview above the editing fields in the UI.
  • Updates internal implementations to handle new UI including
    • RichText
    • Navigation block
    • Button
  • Attempts backwards compatibility risk mitigation due to removal of "preview" state (see below).

Backwards compatibility

Previous the LinkControl had internal states for edit and preview "modes".

Whilst state was internal, this feature was partially exposed in the component API by the addition of the forceIsEditing prop which was original required to allow richtext formats to trigger the Link UI in "edit" mode when first creating a link in rich text. It's usage has since spread to other parts of Core (and likely is also used by 3rd party consumers).

Therefore we need to consider backwards compatibility.

The primary problem is that consumers are used assuming that clicking the Cancel button in the UI will trigger an internal state change in the UI (toggle to "preview" mode) that they have not previously needed to handle. The change in this PR will mean that clicking Cancel would do nothing as there is no longer an preview mode.

To mitigate this I have thought of two options:

Call onChange with current value object

⚠️ This is the current solution I have implemented in this PR. It's up for debate.

When the Cancel button is clicked, the component will call onChange with the current value. As this represents the original value of the control without any modifications, the consuming code should treat this like any other change to the component value. Most consumers treat onChange as a cue to close the UI and thus using it as a proxy for "cancel" seems logical.

If a dedicated onCancel prop is provided however, we do not call onChange and assume that the consumer will handle the rendered state (likely visibility within a Popover) of the control.

However we are making a number of assumptions.

Hide the Cancel button entirely

In this route, we simply hide the Cancel button unless the consumer supplies a dedicated onCancel handler prop. Whilst non-optimal for a UI/UX point of view, this is relatively safe as it makes fewer assumptions.

It does however, leave consumers who haven't passed onCancel without a dedicated Cancel button.

Testing Instructions

  • New Post
  • Switch to Code view
  • Copy the following and paste into the code view text box
<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Standard Rich Text Links</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Hello changes will be <a href="http://www.wordpress.org">link</a></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Link to Attachment</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Link to <a href="http://localhost:8888/wp-content/uploads/2023/09/ice-snowy-rocks-mountains-hd-background-wallpapers-widescreen-high-resolutions-025.jpg" data-type="attachment" data-id="599">media</a></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Navigation Block</h4>
<!-- /wp:heading -->

<!-- wp:navigation {"ref":552} /-->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Button Block</h4>
<!-- /wp:heading -->

<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="http://www.wordpress.org">Hello world</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->
  • Interact with the links in each block and see if it feels natural
  • Test with 3rd party Plugins such as Yoast SEO who are known to consume LinkControl.

Testing Instructions for Keyboard

Screenshots or screencast

https://github.com/WordPress/gutenberg/assets/444434/9187000e-dc7f-426e-a7d9-af83a2cefefe

getdave avatar May 26 '23 09:05 getdave