Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LinkControl] Extract reusable parts #23869

Merged
merged 17 commits into from
Jul 17, 2020
Merged

Conversation

adamziel
Copy link
Contributor

@adamziel adamziel commented Jul 10, 2020

Description

This PR refactors a monolithic LinkControl into separate, bite-sized components and hooks that are reusable. This PR paves ground for reusing the LinkControlSearchInput component in the following interaction designed as a part of #23375:

85623474-75db0a80-b636-11ea-9348-dffea4d2ac71

How has this been tested?

  1. Create a new post
  2. Add navigation block, create a few links
  3. Click the edit link button in the toolbar
  4. Confirm the behavior with and without this PR is exactly the same

Screenshots

Zrzut ekranu 2020-07-10 o 15 38 34

Types of changes

Non-breaking change

@github-actions
Copy link

github-actions bot commented Jul 10, 2020

Size Change: +594 B (0%)

Total Size: 1.15 MB

Filename Size Change
build/block-editor/index.min.js 125 kB +642 B (0%)
build/block-library/index.min.js 132 kB -100 B (0%)
build/edit-site/index.min.js 16.8 kB +9 B (0%)
build/edit-site/style-rtl.css 3.06 kB +21 B (0%)
build/edit-site/style.css 3.06 kB +22 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.min.js 1.14 kB 0 B
build/annotations/index.min.js 3.67 kB 0 B
build/api-fetch/index.min.js 3.43 kB 0 B
build/autop/index.min.js 2.82 kB 0 B
build/blob/index.min.js 620 B 0 B
build/block-directory/index.min.js 7.63 kB 0 B
build/block-directory/style-rtl.css 944 B 0 B
build/block-directory/style.css 945 B 0 B
build/block-editor/style-rtl.css 10.8 kB 0 B
build/block-editor/style.css 10.8 kB 0 B
build/block-library/editor-rtl.css 7.58 kB 0 B
build/block-library/editor.css 7.57 kB 0 B
build/block-library/style-rtl.css 7.77 kB 0 B
build/block-library/style.css 7.77 kB 0 B
build/block-library/theme-rtl.css 728 B 0 B
build/block-library/theme.css 729 B 0 B
build/block-serialization-default-parser/index.min.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.min.js 3.1 kB 0 B
build/blocks/index.min.js 48.3 kB 0 B
build/components/index.min.js 200 kB 0 B
build/components/style-rtl.css 15.6 kB 0 B
build/components/style.css 15.6 kB 0 B
build/compose/index.min.js 9.67 kB 0 B
build/core-data/index.min.js 11.5 kB 0 B
build/data-controls/index.min.js 1.29 kB 0 B
build/data/index.min.js 8.45 kB 0 B
build/date/index.min.js 5.38 kB 0 B
build/deprecated/index.min.js 772 B 0 B
build/dom-ready/index.min.js 568 B 0 B
build/dom/index.min.js 3.23 kB 0 B
build/edit-navigation/index.min.js 10.8 kB 0 B
build/edit-navigation/style-rtl.css 1.08 kB 0 B
build/edit-navigation/style.css 1.08 kB 0 B
build/edit-post/index.min.js 304 kB 0 B
build/edit-post/style-rtl.css 5.61 kB 0 B
build/edit-post/style.css 5.61 kB 0 B
build/edit-widgets/index.min.js 9.35 kB 0 B
build/edit-widgets/style-rtl.css 2.45 kB 0 B
build/edit-widgets/style.css 2.45 kB 0 B
build/editor/editor-styles-rtl.css 537 B 0 B
build/editor/editor-styles.css 539 B 0 B
build/editor/index.min.js 45.1 kB 0 B
build/editor/style-rtl.css 3.78 kB 0 B
build/editor/style.css 3.78 kB 0 B
build/element/index.min.js 4.65 kB 0 B
build/escape-html/index.min.js 733 B 0 B
build/format-library/index.min.js 7.72 kB 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/hooks/index.min.js 2.13 kB 0 B
build/html-entities/index.min.js 621 B 0 B
build/i18n/index.min.js 3.56 kB 0 B
build/is-shallow-equal/index.min.js 711 B 0 B
build/keyboard-shortcuts/index.min.js 2.51 kB 0 B
build/keycodes/index.min.js 1.94 kB 0 B
build/list-reusable-blocks/index.min.js 3.12 kB 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/media-utils/index.min.js 5.32 kB 0 B
build/notices/index.min.js 1.79 kB 0 B
build/nux/index.min.js 3.4 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/plugins/index.min.js 2.56 kB 0 B
build/primitives/index.min.js 1.4 kB 0 B
build/priority-queue/index.min.js 789 B 0 B
build/redux-routine/index.min.js 2.85 kB 0 B
build/rich-text/index.min.js 13.9 kB 0 B
build/server-side-render/index.min.js 2.71 kB 0 B
build/shortcode/index.min.js 1.7 kB 0 B
build/token-list/index.min.js 1.27 kB 0 B
build/url/index.min.js 4.06 kB 0 B
build/viewport/index.min.js 1.85 kB 0 B
build/warning/index.min.js 1.14 kB 0 B
build/wordcount/index.min.js 1.17 kB 0 B

compressed-size-action

@adamziel adamziel force-pushed the update/reusable-link-control-parts branch from c99cdbd to 880fcbf Compare July 10, 2020 13:22
@adamziel adamziel self-assigned this Jul 10, 2020
@adamziel adamziel added [Block] Navigation Affects the Navigation Block [Feature] Link Editing Link components (LinkControl, URLInput) and integrations (RichText link formatting) labels Jul 10, 2020
@adamziel adamziel marked this pull request as ready for review July 10, 2020 13:48
@youknowriad
Copy link
Contributor

youknowriad commented Jul 13, 2020

Do we really need to split it into separate components or should this component be replaced entirely by what the issue is proposing instead? It seems to indicate that it's the whole component that needs to be changed for all these places.

My main concern is that by splitting into smaller components, we'll perpetuate the inconsistencies. For example how is this new component different from URLInput?

@adamziel
Copy link
Contributor Author

adamziel commented Jul 14, 2020

Do we really need to split it into separate components or should this component be replaced entirely by what the issue is proposing instead?

@youknowriad That's the endgame here, I was concerned about doing it all in a single PR as it would likely touch 40+ files and sit in the review queue forever. My plan ATM is to 1. Merge this change 2. Phase out the LinkControl from every place it's used 3. Remove LinkControl entirely. What do you think?

@youknowriad
Copy link
Contributor

Remove LinkControl entirely. What do you think?

Not sure I understand, why not just rename LinkControlSearchInput => LinkControl ?

@adamziel
Copy link
Contributor Author

@youknowriad sure, that works too, the point being getting rid of the current top-level implementation of LinkControl in favor of the new thing. It's not a drop-in replacement though so I will still have to refactor the places where it's used.

@youknowriad youknowriad requested a review from getdave July 14, 2020 08:30
import { useEffect, useState, useRef } from '@wordpress/element';

export default function useCreatePage( customCreatePage = null ) {
const { saveEntityRecord } = useDispatch( 'core' );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can't be used in "block-editor". Anything that has direct relationship with WP API can't be used as the block-editor package is a client only package agnostic to WP context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@youknowriad what do you think would be the right package for this code to live? I can't quite fit this into any existing one. Are these two hooks (useSearchHandler and useCreatePage) enough to justify creating a new package?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like useSearchHandler still fits the block-library as it depends on the editor setting, not on any WP-specific logic. It seems like the same trick should work for the useCreatePage - let me try it.

Copy link
Contributor Author

@adamziel adamziel Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would work but ATM the go-to solution for these things is copying and pasting the code to every package where the editor is initialized. I don't like that so I went back to passing the logic from the navigation-block/edit which ATM is the only consumer of that feature. Let's absolutely revisit later when we talk about the higher level direction for these things.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think there's room for a completely generic LinkControl component inside the @wordpress/components package? (no direct API, no block-editor dependency, just a UI component with potentially some config)

This could allow us to have a storybook story and built it in isolation.

@adamziel
Copy link
Contributor Author

adamziel commented Jul 14, 2020

@youknowriad I think so! I am checking what would it take. LinkControl depends on URLInput at the moment so it would have to be moved there as well. Or would it? Maybe they don't need to be two separate components. It seems like URLInput is an input that supports fetching and rendering arbitrary suggestions, while LinkControl/LinkControlSearchInput exposes the API to do the same plus a bit more page-specific logic. I think these two could become the same component with some sensible, generic defaults.

The only thing that wouldn't move cleanly are useSearchHandler (-> usePageSuggestions?) and useCreatePage hooks so we'd need to find a right place for them to live.

@adamziel
Copy link
Contributor Author

Also, it may be crazy but here's an idea - URLInput doesn't seem to be worthy of it's own component, it's mostly about ensuring that typing triggers searching without duplicate requests and such. It seems like it could be just a reusable hook, with LinkControl as the primary consumer.

@youknowriad
Copy link
Contributor

Yes, on principle I see this too: a Single LinkControl component in UI components, potentially another one in block-editor to "tie it" to the block editor config and use it everywhere. but that's the theory. As you can see there are multiple places where we use these components slightly differently and the discussion we're having here is one I had in the past with @getdave @aduth and others. So for me, it sounds a bit like we're going on circles: building something, another person comes deciding it's not great, having the same discussion.

So, that said, I'm not against, doing another refactor... but it seems that we should ensure that the refactor is actually solving a problem and that we don't end up in a similar position to where we are because in the end-up we find an exception that doesn't fit the scenario.

@youknowriad
Copy link
Contributor

See these issues

#18061
#22439
#22438
#22437
#22435
#20271
#20138
#20136
#20051
#19526
#17293

All these issues are related and I want to make sure we don't end up just creating other issues like that. Should we first audit these issues, define a good plan, check what failed in the past and avoid falling in the same trap?

cc @getdave would love your thoughts here. I'm personally not very aware of the current state of LinkControl to propose a good path forward.

@adamziel
Copy link
Contributor Author

Thank you for these links! Let's not block this PR - I'll investigate the larger issue and propose a way forward (likely in one of these issues).

@adamziel
Copy link
Contributor Author

adamziel commented Jul 14, 2020

With the entity dependency solved, this one is ready for a review. CC @draganescu @noisysocks. I'm investigating what are the options for the larger direction here.

Copy link
Contributor

@draganescu draganescu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested this and it breaks nothing 🚀
Left a minor comment on a component name, but also about the new slot this PR adds.

*/
import { ViewerSlot } from './viewer-slot';

export default function LinkOverview( { value, onEditClick } ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more like LinkPreview ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good note, I'll update it

Copy link
Contributor

@draganescu draganescu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything is awesome! :shipit:

@adamziel adamziel force-pushed the update/reusable-link-control-parts branch from 2b3b7f1 to 5b030bc Compare July 16, 2020 17:44
@adamziel adamziel merged commit 6dba4c0 into master Jul 17, 2020
@adamziel adamziel deleted the update/reusable-link-control-parts branch July 17, 2020 09:50
@github-actions github-actions bot added this to the Gutenberg 8.6 milestone Jul 17, 2020
@adamziel adamziel mentioned this pull request Jul 21, 2020
@crs1138
Copy link

crs1138 commented Jul 27, 2020

Where can I find an example of using the <LinkControl /> component? I'm trying to achieve an editable CTA button that would enable the editor to change the URL and target, rel attributes without the use of the Panel Inspector. Am I even on the right track to use LinkControl component for that?

@adamziel
Copy link
Contributor Author

@crs1138 There are some examples in the readme file here: https://github.com/WordPress/gutenberg/tree/master/packages/block-editor/src/components/link-control

I'm trying to achieve an editable CTA button that would enable the editor to change the URL and target, rel attributes without the use of the Panel Inspector. Am I even on the right track to use LinkControl component for that?

Your thinking is right, however I'm afraid it's not possible at the moment - not only LinkControl does not support editing of target and rel attributes, but also there's also no way to customize it at the moment. I would very much like to have a component that would handle all these use cases and also provide some extension points.

To make LinkControl more flexible, we would either need to add a slot to LinkControl or LinkSettingsDrawer contributing to the surplus of slots, OR export all the building blocks such as LinkControlSearchInput, LinkPreview, LinkControlSettingsDrawer and so on. See this discussion about whether or not the LinkControl component should be the basic building block and some proposed alternatives: #24099

@crs1138
Copy link

crs1138 commented Jul 29, 2020

@adamziel Thanks for the link to the component. The examples there show the use of the component without any context of the use thus I ended up in this thread. I was expecting/hoping it'd have a similar functionality as if using the <URLInputButton />, e.g. in the following code:

...
<Button url={url} >
    <PlainText
        placeholder={ __(`Calling to act`, cvslug) }
        value={btnText || `Click`}
        onChange={ (newText) => setAttributes({ btnText: newText }) }
    />
</Button>
<URLInputButton
    url={ url }
    onChange={ (url, post) => setAttributes( { url, btnText: (post && post.title) || `Click here` } ) }
/>
...

But all I could achieve with the <LinkControl /> component was just an error in the block. I guess for now the only viable solution is using the Panel Inspector.

Btw. interesting read about the challenges and possible solutions regarding the LinkControl alternative approach.

@getdave
Copy link
Contributor

getdave commented Aug 12, 2020

Apologies @youknowriad i missed the ping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Navigation Affects the Navigation Block [Feature] Link Editing Link components (LinkControl, URLInput) and integrations (RichText link formatting)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants