gutenberg
gutenberg copied to clipboard
Remove "preview" mode/step from Link Control component
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:
- requires an extra step to reach the editing of the link
- causes a11y problems relating to perception, focus management and constrained tabbing
- the two modes (edit and preview) are internal to the
LinkControl
and thus require hacks to force editing when required (e.g.forceIsEditing
).
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